4

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.

wangmchn
  • 115
  • 5
  • 1
    I am not sure if it can be done with an init method, but here is a possible solution using a class method: http://stackoverflow.com/a/33200426/1187415. – Martin R Jan 02 '16 at 16:57
  • @MartinR: It seems no way to be done with an init method,too bad. :( but thanks for your answer, I get a solution~ – wangmchn Jan 02 '16 at 17:58

1 Answers1

7

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()
Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148