[iOS] Container view controller
오늘은 Container view controller에 대해 알아볼 예정이다.
주인장은 이 글에 대해 정리하기 전까진 Container view controller가 UIViewController마냥 따로 만들어져있는 클래스 그런건 줄 알았다..ㅎ (나같은 사람 분명 있을거야 ^_^)
시작해보자 ~
Container view controller 란?
Container view controller는 다른 view controller들을 관리하는 view controller의 종류 중 하나이다.
자기 자신의 view를 가지고있는 content view controller와는 다르게 container view controller는 보통 자신의 뷰를 가지고 있지않다. 그럼 container view controller는 도대체 뭐하는 놈인가 ?
Container view controller의 역할은 다른 view controller들을 가지고 관리하는 데에 있다. 따라서, 직접 뷰를 보여줄 일이 없으니 view를 가지고 있지 않은 것이다. Container view controller는 하나 이상의 child view controller를 가지는데 각각의 child view controller는 자체 뷰를 관리하고, container view controller는 자식의 root view의 위치와 크기를 관리한다.
아래 그림을 보면 더 이해가 잘 갈 것이다.
주인장이 헷갈렸다던 Container view controller 클래스의 존재 유무는 이 Container view controller가 하나의 클래스라고 생각했기 때문이었다.
헷갈리지 말아야할 것은 Container view controller는 그냥 개념적인 단어일 뿐 실제로 사용할 땐, 만들어진 UINavigationController 등을 사용하거나 UIViewController를 서브클래싱해서 커스텀하는 형식으로 사용해야한다.
Container view controller의 종류
container view controller의 종류는 아래와 같다.
- UINavigationController
- UISplitViewController → 이 친구는 보통 iPad에서 자주 사용된다 (e.g. 설정 앱)
- UITabBarController
- UIPageViewController
- Custom Container view controller → 이건 그냥 UIViewController 서브클래싱하여 입맛대로 커스텀하여 사용하면 된다
역할과 종류를 알아봤으니 활용 방법도 알아보자.
Child view controller 추가하기
UINavigationController와 같이 애플에서 친절하게 만들어놓은 Container view controller의 경우는 viewControllers라는 프로퍼티를 제공하고 있기 때문에 해당 프로퍼티에 자식 뷰 컨트롤러들을 넣어주면 된다.
class NavigationViewController: UINavigationController {
override func viewDidLoad() {
super.viewDidLoad()
setViewController()
}
func setViewController() {
let firstViewController = FirstViewController()
let secondViewController = SecondViewController()
self.viewControllers = [firstViewController, secondViewController]
}
}
그럼 Custom container view controller에서 자식 뷰 컨트롤러를 추가하고 싶다면 어떻게 해야할까?
아래 과정은 Apple 공식 문서에 나와있는 과정을 번역한 내용이다.
- Container view controller의 addChild(_:) 메소드를 호출한다.
- 자식의 root view를 container view에 추가한다. (addSubView(_:) 메소드 사용)
- 자식의 root view의 위치와 크기에 대한 constraints를 걸어준다.
- 화면 전환이 되었음을 알리기 위해, child view controller의 didMove(toParent:) 메소드를 호출한다.
let storyboard = UIStoryboard(name: "Main", bundle: .main)
if let viewController = storyboard.instantiateViewController(withIdentifier: "imageViewController") as? ImageViewController {
// 1, 2번 과정
addChild(viewController)
view.addSubview(viewController.view)
// 3번 과정
onscreenConstraints = configureConstraintsForContainedView(containedView: viewController.view,
stage: .onscreen)
NSLayoutConstraint.activate(onscreenConstraints)
// 4번 과정
viewController.didMove(toParent: self)
}
Apple에서 만들어놓은 Container view controller 클래스들은 위 과정을 따로 하지 않아도 만들어진 프로퍼티나 메소드를 통해 간단하게 child view controller를 추가할 수 있다.
Child view controller 제거하기
추가를 했으니 제거하는 방법도 알아봐야지 !
아래 과정 또한 Custom container view controller에서 직접 child view controller을 없애는 과정이다.
- child view controller의 willMove(toParent:) 메소드의 값을 nil로 설정해준다.
- 자식의 root view에 대한 constraints를 Deactivate하거나 제거한다.
- 계층 관계를 제거하기 위해 자식의 root view에서 removeFromSuperview() 메소드를 호출한다.
- 마지막으로 container-child 관계를 완전히 없애기 위해, child view controller의 removeFromParent() 메소드를 호출한다.
Apple 공식 문서에 따르면 "container-child 관계를 깬다는 것은 child의 content를 더 이상 보여주지(display) 않겠다는 뜻이며, 다른 child view controller와의 참조(refernce)는 계속 유지될 수 있다." 라고 한다.
추가로 "예를 들면, UINavigationController의 경우, stack으로 child view controller들을 관리하는데, 한 번에 하나 혹은 두 개의 자식과만 container-child 관계를 유지한다." 라고 쓰여져 있었다.
내가 이해한 바로는 container-child 관계는 화면에 보여질 것인가에 대한 유무이고, container view controller가 child view controller를 viewControllers와 같은 프로퍼티로 가지고 있는 것에 대한 관계(?)는 끊이지 않는 것 같다. 즉, child는 위에 적혀있는 과정을 거치면 child는 자신이 들어가는 container view controller에 대한 정보가 사라져 알 수 없게 되는데, container view controller는 계속해서 child view controller을 가지고있기 때문에, 언제든 자신이 필요하면 부를 수 있게 되는 것 같다. (내 생각을 정리한 내용이므로 틀릴 수 있음..틀렸다면 말해주세요..🥺)
Container view
추가로 Container view라는 것에 대해 간단하게 ! 알아보자.
이 container view라는 친구는 코드로는 존재하지 않고 storyboard 상에서만 존재하는 친구이다. 코드에 없다 한 것에서 알 수 있듯 UIContainerView라는 클래스 따위는 없다. (괜히 찾으려다 진땀빼지 마세오..)
인터페이스 상에서 view controller에 container view를 추가했다면 따로 addChild(_:) 메서드를 호출할 필요가 없다.
그리고 container view를 스토리보드 상에서 view controller에 추가해주면 아래 사진과 같이 자동으로 해당 view에 대한 view controller까지 생성해준다 .ᐟ.ᐟ (친절하게 내가 지정한 container view의 크기에 맞게 생성해줌 😲)
저렇게 생성된 view controller에도 custom view controller를 적용시킬 수 있다. (당연함...៖... )
이렇게 오늘은 간단하게 Container view controller에 대해 알아보았다.
이어서 UINavigationController에 대해서도 알아볼 것이다 !
참고자료
[iOS] Container View Controller 란?
1차 수정: 21.09.30 안녕하세요 🐶 이번 시간에는 ViewController 의 종류 중 하나인 Container View Controller 에 대해서 공부해보겠습니다. 그럼 시작할게요🔥 우선 View Controller 를 역할로 구분하자면 크게
woozzang.tistory.com
View Controller Programming Guide for iOS: Implementing a Container View Controller
View Controller Programming Guide for iOS
developer.apple.com
Managing content in your app’s windows | Apple Developer Documentation
Build your app’s user interface from view controllers, and change the currently visible view controller when you want to display new content.
developer.apple.com