ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [iOS] Container View Controller λž€?
    iOS/πŸ€– App 2021. 7. 26. 18:09

    1μ°¨ μˆ˜μ •: 21.09.30

     

    μ•ˆλ…•ν•˜μ„Έμš” 🐢

    이번 μ‹œκ°„μ—λŠ” ViewController 의 μ’…λ₯˜ 쀑 ν•˜λ‚˜μΈ

    Container View Controller 에 λŒ€ν•΄μ„œ κ³΅λΆ€ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

     

    그럼 μ‹œμž‘ν• κ²Œμš”πŸ”₯


     

    μš°μ„  View Controller λ₯Ό μ—­ν• λ‘œ κ΅¬λΆ„ν•˜μžλ©΄ 크게 두 가지 μ’…λ₯˜κ°€ μžˆμŠ΅λ‹ˆλ‹€!

     

    μ²«λ²ˆμ§ΈλŠ” Content View Controller λ‘œμ„œ,

    기본적으둜 λ·° μ»¨νŠΈλ‘€λŸ¬μ—κ²Œ κΈ°λŒ€ν•˜λŠ” μ—­ν• ( μ•± λ‚΄ 데이터λ₯Ό 화면에 λ³΄μ—¬μ£ΌλŠ” λ“±) 을 μˆ˜ν–‰ν•˜λŠ” λ·° μ»¨νŠΈλ‘€λŸ¬μž…λ‹ˆλ‹€.

    일반적으둜 UIViewController λ₯Ό 직접 μ„œλΈŒν΄λž˜μ‹±ν•˜μ—¬ μ»€μŠ€ν…€ν•΄μ„œ μ‚¬μš©ν•˜λŠ” κ²½μš°μž…λ‹ˆλ‹€.

    class MyHomeViewController: UiViewController { ... }

     

     

    λ‘λ²ˆμ§ΈλŠ” 이번 μ‹œκ°„μ— λ‹€λ£° Container View Controller λ‘œμ„œ,

    μ—¬λŸ¬ μš”μ†Œλ₯Ό μ‘°ν•©ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬μ„±ν•˜κ³  ( composite interface )

     

    보톡 직접 무언가λ₯Ό λ³΄μ—¬μ£ΌλŠ” 역할은 μ—†μœΌλ©°,

    λ·° 컨트둀러 간에 λΆ€λͺ¨-μžμ‹ 관계λ₯Ό ν˜•μ„±ν•˜μ—¬ μžμ‹ λ§Œμ˜ λ°©μ‹μœΌλ‘œ μžμ‹μ„ κ΄€λ¦¬ν•˜λŠ” 역할을 λ§‘λŠ” λ·° 컨트둀러 μž…λ‹ˆλ‹€.

    κ°„λ‹¨ν•˜κ²Œ 생각해보면, Container View Controller 듀이 Content View Controller 듀을 κ΄€λ¦¬ν•œλ‹€κ³  μƒκ°ν•˜λ©΄ λ˜κ² λ„€μš”!

     

    그런데 이미 UIKit μ—μ„œ 기본적으둜 μ œκ³΅ν•˜λŠ” System Container View Controller 듀이 μžˆμŠ΅λ‹ˆλ‹€.

    UITabBarController, UINavigationController, UIPageViewController 등이 κ·Έκ²ƒλ“€μž…λ‹ˆλ‹€.

     

    container view controller 라고 λͺ…μ‹œμ μœΌλ‘œ μ ν˜€ μžˆλ‹€.

     

    이 λ•Œ Contianer View Controller λ“€μ˜ νŠΉμ§•μ΄ μžˆμŠ΅λ‹ˆλ‹€.

    μžμ‹ View Controller λ“€μ˜ μ°Έμ‘°λ₯Ό 가지고 κ΄€λ¦¬ν•œλ‹€λŠ” κ²ƒμΈλ°μš”.

    보톡 μ•„λž˜μ™€ 같은 λ°©μ‹μœΌλ‘œ μžμ‹ λ·°μ»¨νŠΈλ‘€λŸ¬μ— μ ‘κ·Όν•  수 있고, μžμ‹ 관계λ₯Ό μƒˆλ‘œ μ„€μ •ν•΄ μ€„μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.

     

     

    그런데 μ™œ ꡳ이 이런 λΆ€λͺ¨-μžμ‹ 관계λ₯Ό λ§Œλ“€μ–΄μ„œ κ΄€λ¦¬ν•΄μ£ΌλŠ”μ§€μ— λŒ€ν•œ 의문이 μƒκΉλ‹ˆλ‹€.

    μ»¨ν…Œμ΄λ„ˆλŠ” μ™œ ν•„μš”ν•œ κ±ΈκΉŒμš”?


     

     

    Container View Controller λŠ” μ™œ ν•„μš”ν• κΉŒ?

     

    🟒  Navigation 둜직 (λΌμš°νŒ…) 을 λΆ„λ¦¬ν•˜μ—¬ 단일 μ±…μž„μ›μΉ™μ„ μ§€ν‚€λ €λŠ” μ‹œλ„μ΄λ‹€.

    " promote better encapsulation by separating out your content

    from how you display that content onscreen"

     

    MVC νŒ¨ν„΄μ„ 곡뢀할 λ•Œ

    λ„ˆλ¬΄λ„ˆλ¬΄ 많이 듀어봀을 Massive View Cotroller 에 λŒ€ν•΄ 아싀거라고 μƒκ°ν•©λ‹ˆλ‹€.

     

    κ°„λ‹¨ν•˜κ²Œ λ·° μ»¨νŠΈλ‘€λŸ¬κ°€ λ„ˆλ¬΄ λ§Žμ€ μ—­ν• (μ±…μž„)을 ν•˜κ³  μžˆλ‹€λŠ” 것인데, λ‹€μŒκ³Ό 같은 μ½”λ“œλ₯Ό ν•œλ²ˆ λ³Όκ²Œμš”.

     

      func showChildVC() {
        // λ·° 컨트둀러λ₯Ό 직접 μƒμ„±ν•œλ‹€
        let childVC = ChildViewController()
    	
        // 직접 μ˜μ‘΄μ„± μ£Όμž…λ„ ν•΄μ€€λ‹€
        childVC.someDedendency = SomeDependency()
    	
        // 직접 화면에 ν‘œμ‹œλ„ ν•΄μ€€λ‹€
        present(childVC, animated: true, completion: nil)
      }

     

    μœ„ μ½”λ“œλŠ” 아무 λ¬Έμ œκ°€ μ—†λ‹€κ³  생각할 수 μžˆμ§€λ§Œ, 이 λ©”μ„œλ“œ μ•ˆμ—μ„œλ„ λ·° μ»¨νŠΈλ‘€λŸ¬λŠ” λ§Žμ€ μ±…μž„μ„ 가지고 μžˆμŠ΅λ‹ˆλ‹€.

     

    1. λ·° 컨트둀러λ₯Ό 직접 μƒμ„±ν•˜μ—¬ 생λͺ…주기에 κ΄€λ €ν•˜κ³ 

    2. μ˜μ‘΄μ„±μ„ μ£Όμž…ν•΄μ£Όκ³ 

    3. 화면에 λ„μ›Œμ£ΌλŠ” μ—­ν• κΉŒμ§€

     

    μ±…μž„μ΄ 많으면 μœ μ§€λ³΄μˆ˜μ™€ ν…ŒμŠ€νŠΈκ°€ νž˜λ“€μ–΄μ§‘λ‹ˆλ‹€.

     

    λ”°λΌμ„œ 화면에 ν‘œμ‹œν•΄μ£ΌλŠ” μ±…μž„μ„ λ‹€λ₯Έ 객체둜 뢄리해 λ‚Έ 것이 μ»¨ν…Œμ΄λ„ˆ λ·° μ»¨νŠΈλ‘€λŸ¬μž…λ‹ˆλ‹€.

     

     

    μ‹œμŠ€ν…œ μ»¨ν…Œμ΄λ„ˆ λ·° 컨트둀러 쀑 ν•˜λ‚˜μΈ

     

    Navigation Controller λ₯Ό 예둜 λ“€λ©΄

     

    μ»¨ν…Œμ΄λ„ˆ λ·° μ»¨νŠΈλ‘€λŸ¬κ°€ μžμ‹ λ·° μ»¨νŠΈλ‘€λŸ¬μ— λŒ€ν•œ ν™”λ©΄ μ „ν™˜μ„ μ–΄λ–€ λ°©μ‹μœΌλ‘œ ν•˜λŠ”μ§€ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

     

       @IBAction func pushSecond(_ sender: Any) {
       
        /* μ—¬κΈ°λŠ” secondVC λ₯Ό μƒμ„±ν•˜λŠ” μ½”λ“œκ°€ λ“€μ–΄κ°‘λ‹ˆλ‹€ */
        
        // 직접 λ‹€μŒ 화면을 ν‘œμ‹œν•˜μ§€ μ•Šκ³ , navigationController 에 μ˜μ‘΄ν•œλ‹€
        navigationController?.pushViewController(secondVC, animated: true)
       }

     

    present(_:animated:completion:) κ³Ό 같은 ν™”λ©΄ 처리 λ©”μ„œλ“œλ₯Ό 직접 ν˜ΈμΆœν•˜μ§€ μ•Šκ³ ,

    navigationController μ—κ²Œ 화면에 ν‘œμ‹œν•  VCλ₯Ό μ „λ‹¬ν•˜μ—¬ νŠΈλžœμ§€μ…˜κ³Ό ν™”λ©΄ ν‘œμ‹œλ₯Ό 맑기고 (μ˜μ‘΄ν•˜κ³ ) μžˆμŠ΅λ‹ˆλ‹€.

     

    pushViewController(_:animated:) 보닀도 μ €λŠ” show(_:sender:) λ₯Ό μ’‹μ•„ν•˜λŠ”λ°μš”...

    μ’€ 더 μΆ”μƒν™”λœ λ©”μ„œλ“œλΌκ³  λ³΄μ‹œλ©΄ 되고, μžμ„Έν•œ λ™μž‘μ€ λ¬Έμ„œλ₯Ό μ°Ύμ•„λ³΄μ‹œλ©΄ 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€.

     

    μ•„λ¬΄νŠΌ μ €λŠ” μ €λŸ° 방식이 μ™„λ²½ν•˜λ‹€κ³  μƒκ°ν•˜μ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€.

    μ—¬μ „νžˆ λ·° 컨트둀러λ₯Ό 직접 μƒμ„±ν•˜κ³ , μ˜μ‘΄μ„± μ£Όμž…λ„ ν•΄μ£ΌλŠ” μ½”λ“œκ°€ ν•„μš”ν•˜λ‹ˆκΉŒμš”.

     

    🟣 λ·° 자체의 ꡬ역을 λΆ„λ¦¬ν•˜μ—¬ μœ μ§€λ³΄μˆ˜κ°€ μš©μ΄ν•΄μ§„λ‹€.

     

    μ»¨ν…Œμ΄λ„ˆ 뷰컨의 루트 λ·°λ₯Ό  λͺ‡ 개의 κ΅¬μ—­μœΌλ‘œ λ‚˜λˆ„μ–΄

    κ΅¬μ—­λ³„λ‘œ νŠΉμ„±μ— 맞게 각각의 λ·° 컨트둀러λ₯Ό 두고 λ”°λ‘œ κ΄€λ¦¬ν•˜λ©΄

    μ±…μž„λ„ λΆ„λ¦¬λ˜κ³  μœ μ§€λ³΄μˆ˜λ„ μ’€ 더 μ‰¬μ›Œ 질 κ²ƒμž…λ‹ˆλ‹€.

     

    μœ„μ˜ μ΄λ―Έμ§€λŠ” UIKit 이 μ œκ³΅ν•˜λŠ” UISplitViewController λ‘œμ„œ

    루트 λ·°λ₯Ό μ™Όμͺ½κ³Ό 였λ₯Έμͺ½ λ‘κ°œμ˜ κ΅¬μ—­μœΌλ‘œ λ‚˜λˆ„μ–΄ κ΅¬μ—­λ³„λ‘œ

    λ‹€λ₯Έ μ±…μž„μ„ κ°€μ§€λŠ” μžμ‹ λ·°μ»¨νŠΈλ‘€λŸ¬λ“€μ„ κ΄€λ¦¬ν•©λ‹ˆλ‹€.

     

    μ•„μ΄νŒ¨λ“œμ—μ„œ μ‰½κ²Œ λ³Ό μˆ˜μžˆλŠ” UI ꡬ성인데, 보톡 μ™Όμͺ½μ— Table VC, 였λ₯Έμͺ½μ— Content VC κ°€ λ“€μ–΄κ°€λŠ” 것 자주 보셨죠?

     

     


     

     

    UIContainerViewController κ°€ κ³΅μ‹λ¬Έμ„œμ— μ—†μ–΄μš” πŸ€”

     

    μ• ν”Œ κ³΅μ‹λ¬Έμ„œμ—μ„œ 찾아보면 μ•„μ‹œκ² μ§€λ§Œ, UIContainerViewController 와 같은 ν΄λž˜μŠ€λŠ” μ—†μŠ΅λ‹ˆλ‹€.

     

    Container View Controller λŠ” ν•˜λ‚˜μ˜ κ°œλ…μ΄λ©°, 기쑴에 μ‘΄μž¬ν•˜λŠ” ν΄λž˜μŠ€λ“€μ„ μ΄μš©ν•΄μ„œ μ»€μŠ€ν…€ κ΅¬ν˜„ν•΄μ•Ό ν•©λ‹ˆλ‹€.

     

    UIViewController λ₯Ό μ„œλΈŒν΄λž˜μ‹±ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

     

    " A custom UIViewController subclass can also act as a container view controller. "

     

    λ§Œμ•½ μ»€μŠ€ν…€ ν•˜μ§€ μ•Šκ³  μ‰½κ²Œ μ‚¬μš©ν•˜κ³  μ‹Άλ‹€λ©΄,

    UINavigationController, UITabBarControler 와 같이 System Container View Controller λ₯Ό μ‚¬μš©ν•΄μ•Όν•©λ‹ˆλ‹€.

     

    이 ν΄λž˜μŠ€λ“€μ€ 클래슀만의 λ°©μ‹λŒ€λ‘œ ν•˜μœ„ λ·° μ»¨νŠΈλ‘€λŸ¬λ“€μ„ κ΄€λ¦¬ν•©λ‹ˆλ‹€.

     

    각 μ»¨ν…Œμ΄λ„ˆ VC λ“€μ˜ νŠΉμ„±λ“€μ„ μ΄ν•΄ν•˜κ³  μš©λ„μ— 맞게 μ‚¬μš©ν•˜λ©΄ λ©λ‹ˆλ‹€.

    λŒ€ν‘œμ μΈ μ‹œμŠ€ν…œ μ»¨ν…Œμ΄λ„ˆ 뷰컨트둀러인 λ„€λΉ„κ²Œμ΄μ…˜ 컨트둀러의 μ˜ˆμ‹œ ( κΈ°λ³Έμ‹œκ³„ μ•± )

     

     

    μ»€μŠ€ν…€ μ»¨ν…Œμ΄λ„ˆ λ·° 컨트둀러의 μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬μ„±ν•˜λŠ” 것은 μ»€μŠ€ν…€ν•˜λŠ” μ‚¬λžŒμ˜ λͺ«μž…λ‹ˆλ‹€.

     

    예λ₯Ό λ“€μ–΄ μžμ‹ λ·° 컨트둀러의 화면을 κ·ΈλŒ€λ‘œ 보여쀄 μˆ˜λ„ 있고,

    μ›ν•˜λŠ” λ ˆμ΄μ•„μ›ƒμ„ μ„€μ •ν•΄μ„œ λ³΄μ—¬μ€„μˆ˜λ„ 있고 ( 예λ₯Ό λ“€μ–΄ ν™”λ©΄ 반반)

    ν˜Ήμ€ 미리 κ΅¬ν˜„λœ container view λ₯Ό μ‚¬μš©ν•΄λ³Ό μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€.


     

    Container View λŠ” 또 λ­”κ°€μš”

     

    "  A container view is a proxy view that stands in for the content of a child view controller. "

     

    μ»¨ν…Œμ΄λ„ˆ λ·°λŠ” μΈν„°νŽ˜μ΄μŠ€ λΉŒλ”μ—μ„œλ§Œ μΆ”κ°€ν•  수 μžˆλŠ” μΌμ’…μ˜ ν”„λ‘μ‹œ λ·°μž…λ‹ˆλ‹€.

    μ»¨ν…Œμ΄λ„ˆ λ·°λŠ” 였브젝트 λΌμ΄λΈŒλŸ¬λ¦¬μ—μ„œλ§Œ μ°Ύμ•„μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

     

    μ•„λž˜ 사진을 λ³΄μ‹œλ©΄

    μ™Όμͺ½μ˜ 씬에 μΆ”κ°€ν•œ Container View λŠ”  

    κΈ°μ‘΄ VC 와 μƒˆλ‘œμš΄ 였λ₯Έμͺ½μ˜ VC 둜 이어진 Embed Segue 둜의 연결을 ν†΅ν•˜μ—¬ μ»¨ν…μΈ λ₯Ό ν‘œμ‹œν•©λ‹ˆλ‹€.

    κ·Έλž˜μ„œ λ§Œμ•½ μ™Όμͺ½ VC μ°Έμ‘° μ–»μœΌλ €λ©΄ prepare(forSegue:~) μ—μ„œ 전달해야함

     

    즉 μ™Όμͺ½μ˜ Container View μ˜μ—­μ— 였λ₯Έμͺ½μ˜ VC 의 λ·° 계측을 λ³΄μ—¬μ£ΌλŠ” 것이죠!

     

    λ·° μ»¨νŠΈλ‘€λŸ¬μ™€ μ—°κ²°λœ Embed Segue 을 보싀 수 μžˆμŠ΅λ‹ˆλ‹€

     

    μ–˜λŠ” κ³΅μ‹λ¬Έμ„œλ„ μ—†μŒ;;;;;;;;;;

    Container View λŠ” κ³΅μ‹λ¬Έμ„œκ°€ μ—†λ‹€

     


     

    Custom Container View Controller κ΅¬ν˜„

     

    기본적인 μ»¨ν…Œμ΄λ„ˆ λ·° 컨트둀러의 λ™μž‘μ„ μˆ˜ν–‰ν•˜λŠ” μ½”λ“œλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

    μ£Όμ„μœΌλ‘œ μ„€λͺ…을 μ²¨λΆ€ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

    // ν˜„μž¬μ˜ λ·° μ»¨νŠΈλ‘€λŸ¬μ— μžμ‹ λ·° 컨트둀러λ₯Ό μΆ”κ°€ν•˜λŠ” μ½”λ“œ
    let storyboard = UIStoryboard(name: "Main", bundle: .main)
    if let viewController = storyboard.instantiateViewController(identifier: "imageViewController")
                                        as? ImageViewController {
    
       // 핡심 λ©”μ†Œλ“œλ‘œμ„œ, λ·° μ»¨νŠΈλ‘€λŸ¬μ— λΆ€λͺ¨-μžμ‹ 관계λ₯Ό ν˜•μ„±ν•œλ‹€
       addChild(viewController)
       
       // μžμ‹ λ·° 컨트둀러의 루트 λ·°λ₯Ό ν˜„μž¬ 뷰의 λ·° 계측에 μΆ”κ°€ν•˜λŠ” μ½”λ“œ
       view.addSubview(viewController.view)
                
       // μ œμ•½ 생성
       onscreenConstraints = configureConstraintsForContainedView(containedView: viewController.view,
                                 stage: .onscreen)
       NSLayoutConstraint.activate(onscreenConstraints)
         
       // ν™”λ©΄ μ „ν™˜μ΄ μ™„λ£Œλ˜μ—ˆλ‹€λ©΄ μžμ‹ λ·° 컨트둀러의 λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜μ—¬ μ•Œλ €μ€€λ‹€.
       viewController.didMove(toParent: self)
    }

    이 뢀뢄에 λŒ€ν•œ μžμ„Έν•œ λ‚΄μš©μ€ μ•„λž˜ μ²¨λΆ€λœ 링크λ₯Ό 확인해보면 λ©λ‹ˆλ‹€


     

     

     

    끝!


    참고자료: https://developer.apple.com/documentation/uikit/view_controllers/creating_a_custom_container_view_controller/

     

    λŒ“κΈ€

μ–΄μ œλ³΄λ‹€ λ°œμ „ν•œ λ‚˜