Custom init of UIViewController from storyboard

后端 未结 3 1115
被撕碎了的回忆
被撕碎了的回忆 2020-12-29 05:52

I tried finding some relevant questions but couldn\'t get anything, hope someone can help.

I set up some UIViewController\'s on a storyboard. I then want to load one

3条回答
  •  無奈伤痛
    2020-12-29 06:01

    Below are two helpers, one is a Storyboard enum, add each and every storyboard in your project as a case under this enum. The name must match the {storyboard_name}.storyboard file. Each view controller in your storyboard should have its storyboard identifier set to the name of the class. This is pretty standard practice.

    import UIKit
    
    public enum Storyboard: String {
        case Main
        case AnotherStoryboard
        //case {storyboard_name}
    
        public func instantiate(_ viewController: VC.Type) -> VC {
            guard
                let vc = UIStoryboard(name: self.rawValue, bundle: nil)
                    .instantiateViewController(withIdentifier: VC.storyboardIdentifier) as? VC
                else { fatalError("Couldn't instantiate \(VC.storyboardIdentifier) from \(self.rawValue)") }
    
            return vc
        }
    
        public func instantiateInitialVC() -> UIViewController {
    
            guard let vc = UIStoryboard(name: self.rawValue, bundle: nil).instantiateInitialViewController() else {
                fatalError("Couldn't instantiate initial viewcontroller from \(self.rawValue)")
            }
    
            return vc
        }
    }
    
    extension UIViewController {
        public static var defaultNib: String {
            return self.description().components(separatedBy: ".").dropFirst().joined(separator: ".")
        }
    
        public static var storyboardIdentifier: String {
            return self.description().components(separatedBy: ".").dropFirst().joined(separator: ".")
        }
    }
    

    Here is how you can instantiate from storyboard with a value set in your view controller. Here is the magic:

    import UIKit
    
    class DetailViewController: UIViewController {
    
        var objectID : Int!
        var objectDetails: ObjectDetails = ObjectDetails()        
    
        internal static func instantiate(with objectID: Int) -> DetailViewController {
    
            let vc = Storyboard.Main.instantiate(DetailViewController.self)
            vc.objectID = objectID
            return vc
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            if((objectID) != nil){
                // In this method I use to make a web request to pull details from an API
                loadObjectDetails()
            }
        }
    }
    

    (Architecture influenced/copies Kickstarter's open source iOS project)

提交回复
热议问题