Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to override init method and return an storyboard instance in swift

In Objective-C, I can easily do this use the following codes:

- (instancetype)init {
    UIStoryboard *sb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    self = [sb instantiateViewControllerWithIdentifier:@"WMViewController"];
    return self;
}

How can I implement this using Swift? I know it is strange to do this, but for some reasons, I must init a viewController like the following:

let vcClass = WMTableViewController.self
// ...
let vc = vcClass.init()

So in order to support storybord / xib, it will be easy if can override init method and return another instance.

Here is the work I am doing:

I am trying to convert my little lib (WMPageController) to Swift (WMPageController-Swift), then I am stucked here.I would be happy if you have another suggestion or solution to deal with it.

Thanks a lot if you would like to help me.

like image 718
wangmchn Avatar asked Mar 13 '23 17:03

wangmchn


1 Answers

Nice question. I tried to solve the same problem in the past.

A specific solution

First of all you could just use a class method

class WMViewController: UIViewController {
    class func loadFromStoryboard() -> WMViewController? {
        return UIStoryboard(name: "main", bundle: nil).instantiateViewControllerWithIdentifier("WMViewController") as? WMViewController
    }
}

And use it like this

let controller = WMViewController.loadFromStoryboard()

A general solution

However adding the loadFromStoryboard method to each ViewController you want to make "loadable" is a bad practice. So we could move that code inside a protocol extension.

protocol StoryboardLoadable { }
extension StoryboardLoadable where Self:UIViewController {
    private static var identifier: String { return "\(Self.self)" }
    static func loadFromStoryboard() -> Self? {
        return UIStoryboard(name: "main", bundle: nil).instantiateViewControllerWithIdentifier(identifier) as? Self
    }
}

Now, all you need to do to add the loadFromStoryboard method to your custom view controller is this single line

extension WMViewController: StoryboardLoadable {}

That's it. Now you can load your view controller writing

let controller = WMViewController.loadFromStoryboard()
like image 69
Luca Angeletti Avatar answered Apr 09 '23 11:04

Luca Angeletti