'swift - Initialize view controller from storyboard by overriding init

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?



Solution 1:[1]

A class factory method is the way to go for now. Here's a protocol that you can use to quickly add makeFromStoryboard support to all UIViewControllers.

protocol StoryboardInstantiable {

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

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

    static func makeFromStoryboard() -> 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" }
}

In case the view controller is the initial view controller in the storyboard, you can simply ignore storyboardIdentifier.

In case all the view controllers are in the same storyboard, you can also override storyboardName under the StoryboardInstantiable extension and return the name.

Solution 2:[2]

You can try Generics. Like this:

func Tvc<T>(_ vcType: T.Type) -> T {
    let vc = (vcType as! UIViewController.Type).vc//?????? UIViewController.Type
    return vc as! T
}

extension UIViewController {
    fileprivate static var vc: UIViewController {
        let M = UIStoryboard.init(name: "V", bundle: Bundle.main)
        return M.instantiateViewController(withIdentifier: "\(self)")
    }
}

Example

let vc = Tvc(HLCases.self)
_vc.navigationController?.pushViewController(vc, animated: true)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 粉红豚Vip