UI 겹침 해결하기(with UIStackView)

EenSung Kim·2024년 2월 23일
0

iOS 앱개발 공부

목록 보기
8/10

공식문서는 답을 알고 있다.

하위 뷰들의 constraints 를 일일히 잡아주지 않아도 되다 보니, 연관있는 뷰들을 묶기 위해 스택뷰를 종종 활용하게 되는데요. 이때 동적으로 하위 뷰를 삭제하고 싶은 경우 주의해야 할 점이 한가지 있습니다.

바로! 스택뷰의 removeArrangedSubview() 대신에 지우고 싶은 뷰의 removeFromSuperview() 를 사용하는 것입니다.

공식문서를 조금 더 꼼꼼히 읽어보았더라면 당연히 해결할 수 있는 문제였는데, 문서를 열심히 본다면서도 왜 이 부분을 놓쳤었는지 모르겠어요. 공식문서는 답을 제시하고 있었습니다.

removeArrangedSubview(_:) 공식문서를 살펴보면 이 메서드는 전달받은 뷰를 스택의 arrangedSubviews 배열에서 제거한다고 안내하고 있습니다. 실제로 다음과 같은 형태로 arrangedSubviews 의 모든 하위 뷰를 삭제하고 프린트를 찍어보면 빈 배열이 나타난다는 걸 알 수 있습니다.

stackView.arrangedSubviews.forEach { view in
    stackView.removeArrangedSubview(view)
}
print(stackView.arrangedSubviews)  // [], 빈 배열 출력

문제는 이렇게 해서는 뷰가 화면에서 제거가 되지 않는다는 점입니다. 추가할 때 분명 arrangedSubviews 에 추가해 주었으니 지울 때에도 여기에서 지우면 될 것 같지만 그렇지 않다는 거죠.

화면에서 뷰를 삭제하려면, removeFromSuperview() 메서드를 명시적으로 호출해 주거나 isHidden 프로퍼티를 true 로 설정해 주어야 합니다.


스택뷰는 왜 이런 복잡한 방법으로 구현된 걸까요?

여기서부터는 (공식 문서에 의존한) 제 추측을 섞어서 말씀드려볼까 합니다.

subviews

뷰들은 계층 구조를 이룹니다. 쉽게 말해서 부모와 자식 관계를 가진다는 것이죠. 우리는 이러한 계층에 대한 정보를 뷰의 subviews 프로퍼티를 통해 얻을 수 있습니다. subviews 프로퍼티는 모든 뷰가 가져야 하는 필수적인 정보이기 때문에 UIView 클래스가 갖고 있는 프로퍼티이기도 합니다.

하지만 subviews 는 그 자체로 하위의 뷰들이 어떤 constraints, 다시 말해 어떠한 오토레이아웃 제약 조건들을 가져야 하는지를 알려주지는 않습니다. 그저 계층 구조에 대한 정보만을 전달하기 때문입니다.

arrangedSubviews

하위 뷰들의 레이아웃을 일일히 관리해주지 않아도 된다는 강점 때문에 스택뷰를 활용한다고 말씀드렸는데요. 그렇다면 스택뷰는 어떻게 하위뷰들을 관리할 수 있는 것일까요?

이때 등장하는 것이 바로 arrangedSubviews 입니다. arrangedSubviews 배열 안에 추가된 뷰들은 스택뷰의 축(axis) 을 따라 순서대로 정렬됩니다. 그리고 axis, distrivution, alignment, spacing 및 다른 프로퍼티를 통해 세부적인 레이아웃이 결정되죠. 따라서 arrangedSubviews 배열에 뷰가 있다는 것은, 자신의 레이아웃을 스택뷰의 정보에 의존해서 결정하겠다는 의미가 됩니다.


종합하면 스택뷰는, 모든 뷰들이 그런 것처럼, 자신이 갖는 하위 계층의 뷰들을 subviews 로 관리합니다. 다만 스택뷰는 추가적으로 arrangedSubviews 배열을 통해 자신의 속성에 따라 정렬하여 관리할 서브뷰들을 별도로 관리하게 되는 것이죠.

그래서 뷰를 삭제하기 위해서는 arrangedSubviews 에서 제거하는 것이 아닌 subviews 에서 제거해야 하고, removeFromSuperview() 메서드를 사용해야 하는 것입니다.

실제로 arrangedSubviews 프로퍼티 문서를 확인해보면, 추가할 때는 addArrangedSubview() 지울 때는 removeFromSuperview() 를 활용해야 하며, 이 메서드들이 호출될 때 스택뷰는 자동으로 뷰를 subviews 에 추가하거나 또는 arrangedSubviews 에서 제거한다고 합니다.

위 내용이 복잡한 것 같다면 이것만 기억하면 될 것 같네요.

스택뷰에 뷰를 추가할 때는 addArrangedSubview()
스택뷰에서 뷰를 제거할 때는 해당하는 뷰의 removeFromSuperview()

profile
iOS 개발자로 전직하기 위해 공부 중입니다.

0개의 댓글

관련 채용 정보