안녕하세요! ✋

 

주니오스입니다.

 

오늘은 커스텀 탭바를 만들어봄과 동시에 컨테이너 뷰 컨트롤러에 대해서도 학습해 보려고 합니다.

 

먼저, 아시다시피 뷰 컨트롤러에는 두가지 역할이 있는데요.

 

바로 컨텐츠를 표시할 UIView를 관리하는 역할인 컨텐츠 뷰 컨트롤러가 있습니다.

 

그리고 다수의 뷰 컨트롤러들을 자식 뷰 컨트롤러표 보유하며 관리하는 컨테이너 뷰 뷰컨트롤러가 있습니다.

 

전자의 경우는 익숙하지만, 후자의 경우 조금 어렵더군요.

 

먼저 커스텀 탭바를 만들어 볼 것인데요 구조는 아래와 같습니다.

 

 

커스텀 탭바 구조

 

오른쪽 UIWindow위에 그려진 것이 디바이스 화면에 표시되는 레이아웃입니다.

 

아래에 화면을 선택할 수 있는 탭바가 있고, 바로위에 이에 상응하는 화면이 나오게 됩니다.

 

왼쪽그림에서 우선 가장 바깥쪽에 있는 것이 TabBarContainer로 Scene에 rootViewController입니다.

 

탭바 컨테이너는 네비게이션 컨테이너를 자식으로 둡니다.

 

네비게이션 컨테이너와 탭바 컨테이너에 있는 view는 해당 뷰 컨트롤러의 기본 UIView(뷰계층의 루트)입니다. (아시는 그게 맞습니다.)

 

여기서 주목할 점은 서로다른 뷰 컨트롤러가 하나의 뷰계층을 구성한다는 것입니다.

 

탭바 컨테이너는 탭바를, 네비게이션 컨트롤러는 탭바위 화면을 구성하고 있습니다.

 

특정 뷰계층에 다수의 뷰컨트롤러가 개입하려면 부모-자식 관계를 설정해야 합니다.

 

위 구조에서 네비게이션 컨테이너는 탭바 컨테이너의 자식 뷰컨트롤러입니다.

 

addChild매서드를 통해서 자식 뷰컨트롤러를 설정할 수 있습니다.

 

private func setupView() {
    
    // 뷰 컨트롤러들을 배열에 저장해두고 가져오는 식으로 진행
    let selectedVC = viewControllers[selectedIndex]
    
    // willMove를 자동으로 호출한다.
    
    // 현재 뷰컨트롤러의 자식뷰컨트롤러를 지정하는 경우에 호출된다
    self.addChild(selectedVC)
    
    // ✅ 커스텀 컨테이너 구현시, addChild이후에 반드시 호출해야한다.
    selectedVC.didMove(toParent: self)
    
    // 컨테이너의 뷰계층에 selectedVC.view를 추가한다.
    view.insertSubview(selectedVC.view, belowSubview: tabBarView)
    
    ...
}

 

위 함수는 특정 탭바위 아이템을 클릭했을 때 화면에 보일 뷰컨트롤러를 업데이트 합니다.

 

addChild호출 이후 insertSubView가 호출되는 것을 확인할 수 있습니다.

 

특정 뷰컨트롤러를 삭제하는 경우 아래 함수가 호출됩니다.

 

private func deleteView() {
    
    guard let prev = previewsIndex else { return }
    
    let previousVC = viewControllers[prev]
    
    previousVC.view.removeFromSuperview()
    
    // ✅ 커스텀 컨테이너 구현시 removeFromParent호출전 willMove를 반드시 호출해야한다.
    previousVC.willMove(toParent: nil)
    
    previousVC.removeFromParent()
    
    // 제거후, didMove를 자동으로 호출
    
}

 

 

코드를 보면 willMove, didMove함수를 볼 수 있는데요 아래 설명해 두었습니다.

 

더보기

willMove, didMove에 대해서

 

뷰 컨트롤러는 자신이 특정 뷰 컨트롤러의 자식 뷰 컨트롤러가 되거나, 그 상태에서 벗어나는 경우

특정 함수를 자동으로 호출합니다.

그것이 willMove와 didMove입니다.

 

일반적으로 애플에서 구현한 UINavigationController와 같은 뷰 컨트롤러에 포함되는 경우 

자동으로 이 함수들이 호출됩니다.

 

하지만, 위와같이 커스텀으로 컨테이너를 구현하는 경우는 예외사항이 있습니다.

 

수동으로 해당함수들을 호출해야하는 시점이 있습니다.

 

  addChild removeFromParent
willMove 자동 수동
didMove 수동 자동

 

이 부분을 유의해서 구현하시면 됩니다. :D

 

 

구현한 커스텀 탭바는 다음과 같습니다.

 

커스텀 탭바

 

여기까지 커스텀 탭바를 구현하는데 필요한 코어 개념들을 알아보았습니다.

 

전체코드가 궁금하시다면 아래 Gist를 참고해 주세요!

 

감사합니다~

 

 

 

CustomTabBarView(UIKit)

CustomTabBarView(UIKit). GitHub Gist: instantly share code, notes, and snippets.

gist.github.com