Custom init of UIViewController from storyboard Custom init of UIViewController from storyboard ios ios

Custom init of UIViewController from storyboard


A simplification of my prior answer which is quick and avoids alternative hacky fixes:

Here is a detail view controller you may want to instantiate from storyboard with an objectID set:

import UIKitclass DetailViewController: UIViewController {    var objectID : Int!    internal static func instantiate(with objectID: Int) -> DetailViewController {        let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailViewController") as DetailViewController        vc.objectID = objectID        return vc    }    override func viewDidLoad() {        super.viewDidLoad()        if((objectID) != nil){            print("Here is my objectID: \(objectID)")        }    }}

Here is how you would use it to push onto a navigation controller with objectID set to 1:

self.navigationController.pushViewController(DetailViewController.instantiate(1), animated: true)

Added a blog post:https://theswiftcook.wordpress.com/2017/02/17/how-to-initialize-a-storyboard-viewcontroller-with-data-without-segues-swift-3-0git/

Link to example on GitHub:https://github.com/hammadzz/Instantiate-ViewController-From-Storyboard-With-Data


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 UIKitpublic enum Storyboard: String {    case Main    case AnotherStoryboard    //case {storyboard_name}    public func instantiate<VC: UIViewController>(_ 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 UIKitclass 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)


An (ugly) way to solve this issue:

You can set your let i from an external buffer in your code (AppDelegate variable in this example)

required init?(coder aDecoder: NSCoder) {    self.i = UIApplication.shared().delegate.bufferForI    super.init(coder: aDecoder)}

And when you initiate your UIViewController through Storyboard:

UIApplication.shared().delegate.bufferForI = myIValueself.navigationController!.pushViewControllerFading(self.storyboard!.instantiateViewController(withIdentifier: "myViewControllerID") as UIViewController)

EDIT:You don't have to pass the value through the AppDelegate. Better answer here.