관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] ViewController에 다른 ViewController embed 방법 (ContainerView, ContentsViewController, addChild, removeFromParent, didMove, willMove를 사용하는 이유) 본문

iOS 기본 (swift)

[iOS - swift] ViewController에 다른 ViewController embed 방법 (ContainerView, ContentsViewController, addChild, removeFromParent, didMove, willMove를 사용하는 이유)

jake-kim 2021. 9. 9. 22:35

ViewController의 자식으로 UIViewController를 삽입 / 삭제

대표적인 ContainerView를 사용하여 ViewController 관리하는 클래스

  • navigationController
  • TabBarController
  • PageViewController

ContainerView에 ContentViewController 추가 및 삭제

  • 추가
private func addContentsView() {
    addChild(contentTableView)
    contentTableView.view.frame = containerView.frame
    containerView.addSubview(contentTableView.view)
    contentTableView.didMove(toParent: self)
}
  • 삭제
@objc
private func removeContentsView() {
    contentTableView.willMove(toParent: nil)
    contentTableView.removeFromParent()
    contentTableView.view.removeFromSuperview()
}

addChild, removeFromParent, didMove, willMove,  사용하는 이유

  • addChild / removeFromParent: ViewController들은 children property를 갖는데, children 배열에 삽입되어 마치 navigationController처럼 child를 관리하기 쉽도록 내부적으로 제공해주는 프로퍼티 children배열에 저장하는 것 (추후에 child 사용을 대비하여 넣어놓는 것)
private func addContentsView() {

    print(children) // []

    addChild(contentTableView)
    contentTableView.view.frame = containerView.frame
    containerView.addSubview(contentTableView.view)
    contentTableView.didMove(toParent: self)

    print(children) // [<ContainerViewEx.MyTableViewController: 0x7f9312712550>]
}
  • didMove / willMove: viewController들은 didMove(toParent:), willMove(toParent:)라는 함수를 viewWillAppear과 같이 viewController의 생명주기에서 부모가 생긴 경우 특정 이벤트를 처리해야 하는 경우, 아래와 같이 override하여 추후에 처리할 것을 대비하여 didMove / willMove를 호출해주는 것
override func didMove(toParent parent: UIViewController?) {
    super.didMove(toParent: parent)

    print("MyTableViewController didMove 호출 parent(\(parent)) !!!")
}

override func willMove(toParent parent: UIViewController?) {
    super.willMove(toParent: parent)

    print("MyTableViewController willMove 호출 parent(\(parent)) !!!")
}
  • add할때 willMove만 따로 명시적으로 호출하는 이유: add할때 addChild()에서 내부적으로 willMove만 호출
    • 뷰가 추가된 후 특정 작업들을 해야할것이 있다면 끝낸 후 didMove(toParent:)를 타이밍에 맞게 호출될 수 있게 하기위함
  • remove할때 willMove만 따로 명시적으로 호출하는 이유: remove할때 removeFromParent()에서 내부적으로 didMove만 호출되고 willMove는 호출되지 않는 형태
    • viewController가 제거되기 전에 작업해야할 것들을 준비 후 willMove(toParent:nil)을 타이밍에 맞게 호출될 수 있게끔 하기위함

* 전체 소스코드: https://github.com/JK0369/ContainerViewEx

* 참고

- Apple Document: https://developer.apple.com/documentation/uikit/view_controllers/creating_a_custom_container_view_controller/

Comments