Creating a generic UViewController initializer

I am trying to create an extension UIViewController

that I can use to initialize new instances. For each view controller in my project, I have a corresponding storyboard.

i.e.

EditSomethingViewController.swift
EditSomethingViewController.storyboard

      

This is what I have so far:

extension UIViewController {

    static func initalize() -> UIViewController? {
        let name = String(self)

        let storyboard = UIStoryboard(name: name, bundle: nil)

        return storyboard.instantiateInitialViewController()
    }

}

      

However, this means that when I use it, I still need to return an answer.

i.e.

if let viewController = EditSomethingViewController.initalize() as? EditSomethingViewController {
     // do something with view controller here  
}

      

Is it possible to create an extension in such a way that I cannot give an answer?

ps Working on an old project written in Swift 2.3 would appreciate the answers that are supported.

+3


source to share


3 answers


I am using this extension:

extension UIViewController
{
    class func instantiateFromStoryboard(_ name: String = "Main") -> Self
    {
        return instantiateFromStoryboardHelper(name)
    }

    fileprivate class func instantiateFromStoryboardHelper<T>(_ name: String) -> T
    {
        let storyboard = UIStoryboard(name: name, bundle: nil)
        let controller = storyboard.instantiateViewController(withIdentifier: String(describing: self)) as! T
        return controller
    }
}

      



Using:

let controller = MyViewController.instantiateFromStoryboard()

      

+2


source


You can change the return type as Self

to match the type you are calling the method on.

This is the method I used to do this. Instead, it should be placed in a protocol extension.



static func loadFromStoryboard() -> Self? {
    let storyboard = UIStoryboard(name: NSStringFromClass(self),
                                  bundle: Bundle(for: self))
    return storyboard.instantiateInitialViewController() as? Self
}

      

0


source


I assume you don't want each of your VCs to manually match the protocol. It will be too much work :)

I haven't tested this, but this should work:

protocol Initializable {
    static func initalize() -> Self?
}

extension UIViewController: Initializable {
    static func initalize() -> Self? {
        let name = NSStringFromClass(self as! AnyClass)

        let storyboard = UIStoryboard(name: name, bundle: nil)

        return storyboard.getInitialVC(type: self)
    }
}

extension UIStoryboard {
    func getInitialVC<T: UIViewController>(type: T.Type) -> T? {
        return instantiateInitialViewController() as? T
    }
}

      

0


source







All Articles