IBOutlet link to embedded view controller

前端 未结 4 895
刺人心
刺人心 2021-02-02 07:29

I have a complex iPad view that I manage by having several view controllers. I previously (before iOS6/XCode 4.5) did this by allocating my view controllers in code, and hooked

4条回答
  •  情歌与酒
    2021-02-02 08:08

    Note of Caution

    Before proceeding to use an answer to this question, you may wish to reflect whether the embedded things really need to be view controllers.

    Eg, if you're embedding a UICollectionViewController subclass, could you instead embed a UICollectionView subclass? Or, even better, could you embed a UIView subclass that hides away the UICollectionView behind a simple ViewModel?

    In the code base I'm currently working on, I'm embedding two view controllers in to another view controller. Both could fairly easily be plain views instead, and could then be more easily bound to in the storyboard, without this messy code.

    Unfortunately, they are currently view controllers and I'm not in a position to simplify them in to plain views right now, so this will have to do.

    Background

    I'm using the approach of picking up the embed segue in prepare(for segue:, sender:) as suggested by Playful Geek here.

    I wanted to show the swift I'm using for this, as it seems to be fairly tidy…

    class EditionLandingViewController: UIViewController {
        fileprivate var titlesView: SectionTitlesViewController!
        fileprivate var sectionsView: SectionsViewController!
    }
    
    //MARK:-
    
    extension EditionLandingViewController {
        private enum SegueId: String {
            case embedTitles
            case embedSections
        }
    
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            super.prepare(for: segue, sender: sender)
    
            guard
                let segueRawId = segue.identifier,
                let segueId = SegueId(rawValue: segueRawId)
                else { return }
    
            switch segueId {
            case .embedTitles:
                self.titlesView = segue.destination as! SectionTitlesViewController
    
            case .embedSections:
                self.sectionsView = segue.destination as! SectionsViewController
            }
        }
    }
    

    Discussion

    I've chosen to name segues as action methods.

    Using an enum cases for segue identifiers means you've got the compiler and tooling on your side, so its much harder to get a segue name wrong.

    Keeping the segue ids in a private enum within the extension scope seems appropriate in this case as these segues are not needed anywhere else (they can't be performed, for example).

    I'm using implicitly unwrapped types for the embedded view controllers because (in my case anyway) it's a logic error if they are missing.

    Similarly, I'm also happy to force cast the destination view controller types. Again, it would be a logic error if these types are not the same.

提交回复
热议问题