버그 잡이

swift - viewController에 viewController 추가하기 #addChild() 본문

카테고리 없음

swift - viewController에 viewController 추가하기 #addChild()

버그잡이 2020. 11. 10. 10:34

UIView와 같은 경우 ViewController 하위에 포함시키고자 할때 객체를 생성해서 addSubView 해주면 됩니다.

그런데 ViewController를 ViewController 안에 추가하고 싶은 경우는 어떻게 할까요?

 

공식 문서를 보면 아래 4가지의 메서드가 필요하다고 합니다.

  • addChild(_:)

  • removeFromParent()

  • willMove(toParent:)

  • didMove(toParent:)

아래와 같이 사용합니다.

parentVC.addChild(childVC)
parentVC.view.addSubView(childVC)
childVC.willMove(toParent: parent)
childVC.didMove(toParent: parent)

UIView를 포함시키는 것과 다르게

.addChild() , .didMove(), .willMove() 라는 메서드가 사용됩니다.

 

 

addChild()

This method creates a parent-child relationship between the current view controller and the object in the childController parameter. This relationship is necessary when embedding the child view controller’s view into the current view controller’s content. If the new child view controller is already the child of a container view controller, it is removed from that container before being added.

공식 문서를 보면 ViewController 간에 parent-child 관계를 만들기 위해서는 해당 메서드가 필수적이라고 합니다.

특이사항으로 같은 childVC를 서로 다른 parentVC에 동시에 관계를 성립할 수는 없다고 합니다.

그런데 한 parentVC가 여러개의 childVC를 가질 수 있습니다.

addChild() 메서드의 정의를 들어가보면 [UIViewController] 로 배열인 것을 확인할 수 있습니다.

 

extension UIViewController {

    // An array of children view controllers. This array does not include any presented view controllers.
    @available(iOS 5.0, *)
    open var children: [UIViewController] { get }

    /*
      If the child controller has a different parent controller, it will first be removed from its current parent
      by calling removeFromParentViewController. If this method is overridden then the super implementation must
      be called.
    */
    @available(iOS 5.0, *)
    open func addChild(_ childController: UIViewController)

...

}

 

 

didMove()

Called after the view controller is added or removed from a container view controller.

willMove()

Called just before the view controller is added or removed from a container view controller.

위 메서드들은 childVC가 parentVC에 붙기 직전, 붙은 후 / 제거되기 직전, 제거된 후 이를 알려주는 메서드입니다. 이를 통해 childVC는 parentVC에 추가, 삭제 되는 등의 상황에 반응할 수 있습니다.

childVC 입장에서는 parentVC에 추가되는 정확한 시점을 알 수 없기 때문에 이 메서드를 활용하여 적절하게 반응하는 것입니다.

 

 

Custom Embedder

아래와 같이 embeder 객체를 만들어 사용할 수도 있습니다.

 

// https://stackoverflow.com/a/47764799

class ContainerViewEmbedder {
    class func embed(
        parent:UIViewController,
        container:UIView,
        child:UIViewController,
        previous:UIViewController?) {

        child.willMove(toParent: parent)
        parent.addChild(child)
        container.addSubview(child.view)
        child.didMove(toParent: parent)
        child.view.snp.makeConstraints {
            $0.edges.equalToSuperview()
        }
    }
    
    class func embed(child: UIViewController, parent:UIViewController, container:UIView,
                     completion:((UIViewController)->Void)? = nil) {
        embed(
            parent: parent,
            container: container,
            child: child,
            previous: parent.children.first
        )
        completion?(child)
    }
}
반응형
Comments