오늘은 UIStackView
에 어떻게 view를 추가할 수 있는지 알아보자.
포스팅 제목이 addArrangedSubview
vs addSubView
이다.
이렇게 정한 이유는 StackView
에 동적으로 subView
들을 추가할때 헷갈렸던 부분이기도 했고, 그때는 자세하게 이해하고 넘어갈 생각을 하지 않았어서 이제와서 해보려 한다..!ㅋㅋㅋ
iOS 개발을 하다보면 UIStackView
를 많이 사용하게 된다.
처음부터 모든 콘텐츠를 알 수 있다면 좋겠지만 UIStackView
안의 view
들을 다이나믹하게 관리해야할 때가 있다.
그럴때는 보통 코드를 통해 UIStackView
에 subView
를 추가하게 된다.
공식문서로 UIStackView
에 대해서 알아보자
(출처: https://developer.apple.com/documentation/uikit/uistackview)
StackView
를 사용하면 오토레이아웃의 기능을 활용하여 기기의 방향, 화면 크기 및 사용 가능한 공간의 모든 변경 사항에 동적으로 적용할 수 있는 사용자 인터페이스를 만들 수 있다.
StackView
는 arrangedSubviews
프로퍼티로 모든 view들의 레이아웃을 관리한다.
arrangedSubviews
는 StackView
의 axis에 따라 정렬되어 있다.
arrangedSubview
라는 프로퍼티로StackView
안의 view들을 관리한다는 것을 알았다.
공식문서로 arrangedSubviews
를 확인해보자.
(출처: https://developer.apple.com/documentation/uikit/uistackview/1616232-arrangedsubviews)
arrangedSubviews
는 정렬된 스택뷰의 뷰들 리스트라고 한다.
위의 그림처럼 1, 2, 3이라는 view들을 subView로 갖는 vertical stack view
가 있다고 생각해보자.
위의 vertical stack view
의 arrangedSubviews
프로퍼티는 [1, 2, 3]일 것이다.
arrangedSubviews
프로퍼티는 스택뷰의 뷰들의 리스트이고, 스택 뷰의 축의 방향에 따라 정렬된 값을 갖기 때문이다.
addArrangedSubview(_:)
와 insertArrangedSubview(_:at:)
로 스택뷰에 subView를 추가할 수 있다.
공식문서로 addArrangedSubview(_:)
를 확인해보자.
(출처: https://developer.apple.com/documentation/uikit/uistackview/1616227-addarrangedsubview)
addArrangedSubview(_:)
는arrangedSubviews
배열의 끝에 뷰를 추가하는 메서드이다.
이 메서드는 파라미터로 입력 받은 뷰가 이미 스택 뷰의 subView
가 아닌 경우 스택 뷰의 subView
로 자동 추가한다.
즉, 이미 스택 뷰의 subView
인 경우에는 순서를 변경하지 않는다.
@IBOutlet weak var stack: UIStackView!
override func viewDidLoad() {
let blueView = makeView(.blue)
stack.addArrangedSubview(blueView)
}
private func makeView(_ color: UIColor) -> UIView {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = color
view.heightAnchor.constraint(equalToConstant: 200).isActive = true
return view
}
필요한 subView
를 만들어 반환하는makeView(_:)
메서드를 정의했다.
blue
를 배경색으로 갖는 뷰를 스택 뷰에 추가했다.
우리가 원하는대로 파란 배경색을 갖는 뷰가 스택 뷰에 추가되었다.
subView
인 뷰를 추가하면 어떻게 될까?이 메서드는 파라미터로 입력 받은 뷰가 이미 스택 뷰의
subView
가 아닌 경우 스택 뷰의subView
로 자동 추가한다.
이 메서드에 대해 설명하면서 위와 같은 설명도 덧붙였다.
설명대로라면 이미 스택 뷰의 subView
인 뷰를 addArrangedSubview(_:)
한다면 아무 일도 안 일어날거 같다.
한 번 확인해보자.
@IBOutlet weak var stack: UIStackView!
override func viewDidLoad() {
let blueView = makeView(.blue)
stack.addArrangedSubview(blueView)
stack.addArrangedSubview(blueView)
}
private func makeView(_ color: UIColor) -> UIView {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = color
view.heightAnchor.constraint(equalToConstant: 200).isActive = true
return view
}
blueView
를 두 번 addArrangedSubview(_:)
해봤다.
결과는 아까와 동일하게 나타난다.
배경색이 같아서 확인이 안되는거일수도 있으니 다시 자세하게 확인해보자.
stackView
에 UIView
가 하나만 들어가 있는 모습을 확인할 수 있다.
공식문서로 insertArrangedSubview(_:at:)
를 확인해보자.
(출처: https://developer.apple.com/documentation/uikit/uistackview/1616237-insertarrangedsubview)
입력 받은 인덱스에 입력 받은 뷰를 정렬된
subView
들의 배열에 추가한다.
스택 뷰의 arraySubViews
에 이미 존재하는 인덱스라면 arraySubViews
배열의 크기를 늘리고 입력 받은 인덱스의 자리를 비우기 위해 해당 인덱스부터 subView
들의 자리를 한 칸씩 뒤로 이동한다.
인덱스에 입력 받은 뷰가 들어갈 자리를 마련하고 스택 뷰는 입력 받은 뷰를 해당 인덱스에 저장한다.
removeArrangedSubview(_:)
스택뷰에서 subView를 제거할 수 있다.
공식문서로 removeArrangedSubview(_:)
를 확인해보자.
(출처: https://developer.apple.com/documentation/uikit/uistackview/1616235-removearrangedsubview)
removeArrangedSubview(_:)
는arrangedSubviews
배열에서 입력받은view
를 제거하는 메서드이다.
이 메서드를 통해 제거된 뷰들의 위치와 크기는 더 이상 스택 뷰에서 관리되지 않는다.
이 메서드로 UIStackView
의 arrangedSubviews
배열에서 입력 받은 뷰를 제거할 수는 있지만 그 뷰는 계속 뷰의 hierarchy에 남아 있는다.
위의 그림처럼 파란색, 초록색 배경색을 가진 뷰들을 stackView
의 subView
로 추가했다.
stackView
의 arrangedSubviews
프로퍼티에 두개의 뷰가 출력되는걸 확인할 수 있다.
그렇다면 이제 removeArrangedSubview(_:)
로 파란색 배경색 뷰를 제거해보자.
removeArrangedSubView(_:)
로 파란색 배경색 뷰를 arrangedSubviews
배열에서 제거했다.
화면에서도 파란색 배경색 뷰가 사라진거 같다.
좀 더 자세하게 알아볼까?
화면에는 초록색 배경색 뷰만 그려졌으니 View hierarchy에는 StackView에 하나의 view만 들어 있어야하는데 두개가 들어가 있다.
즉, removeArrangedSubview(_:)
를 사용하면 arrangedSubviews
배열에서 뷰를 제거할 수는 있지만 View hierarchy에서는 제거를 하지 못한다.
이에 대한 해답은 애플 공식 문서에서 찾을 수 있었다.
removeArrangedSubview(_:)
메서드를 호출한 후 뷰가 화면에 나타나지 않도록하려면 뷰의 removeFromSuperview()
메서드를 호출하여 뷰를 명시적으로 제거하거나 뷰의 isHidden
속성을 true
로 설정한다.
removeArrangedSubview(_:)
메서드를 호출해 arrangedSubviews()
배열에서 뷰를 제거했다.
제거하려는 뷰에서 removeFromSuperview()
메서드를 호출해 View hierarchy에서도 제거했다.
이전에는 의례 이렇게 써야지 되는구나 했었는데 오늘 정리를 하면서 왜 이렇게 써야되는지 알게되었다.
역시... 공부를 해야...ㅋㅋㅋ
그럼 이만👋
라자냐, 많은 도움이 됐습니다. 감사해요! ☺️