Home » Swift » swift – Initialize view controller from storyboard by overriding init

swift – Initialize view controller from storyboard by overriding init

Posted by: admin November 30, 2017 Leave a comment

Questions:

I have a ViewController instance defined in a storyboard. I can initialize it by the following

var myViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("myViewControllerIdentifier") as! ViewController

Is there a way to override the init method of ViewController so that I can initialize it using

var myViewController = ViewController()

I tried overriding init

convenience init() {
    self = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}

but the compiler doesn’t like that. Any ideas?

Answers:

A convenience initializer must always delegate to a designated initializer for the same class, and a designated initializer must call a superclass initializer.

Since the superclass doesn’t have an appropriate initializer, you would probably be better served by a class factory method:

static func instantiate() -> SearchTableViewController
{
    return UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}

then use:

var myViewController = SearchTableViewController.instantiate()

Questions:
Answers:

A class factory method is the way to go for now. Here’s a protocol that you can use to quickly add instantiate() support to all your UIViewControllers.

protocol StoryboardInstantiable {

    static var storyboardName: String { get }
    static var storyboardBundle: NSBundle? { get }
    static var storyboardIdentifier: String? { get }
}
​
extension StoryboardInstantiable {

    static var storyboardIdentifier: String? { return nil }
    static var storyboardBundle: NSBundle? { return nil }

    static func instantiate() -> Self {
        let storyboard = UIStoryboard(name: storyboardName, bundle: storyboardBundle)

        if let storyboardIdentifier = storyboardIdentifier {
            return storyboard.instantiateViewControllerWithIdentifier(storyboardIdentifier) as! Self
        } else {
            return storyboard.instantiateInitialViewController() as! Self
        }
    }
}

Example:

extension MasterViewController: StoryboardInstantiable {

    static var storyboardName: String { return "Main" }
    static var storyboardIdentifier: String? { return "Master" }
}