'How to use Storyboards with factory pattern View Controller instantiation?

How do I control View Controller creation using storyboards? After reading on here about the benefits of encapsulation & the problems with singletons, Ive refactored my code. I use a factory to instantiate my vc's & supply them with their dependencies. But now I want to use storyboards. Is there a way to get the storyboard to call the factory method? At present, when I need to instantiate a child view controller I have code like this:

UIViewController *vc = [self.factory buildChildViewController];

and in the factory method all the dependencies are taken care of:

- (UIViewController*) buildChildViewController {
    ChildViewController *cvc = [[ChildViewController alloc] initWithNibName:nil bundle:nil];
    [cvc setDatabase:self.database];
    [cvc setQuery:[self buildSomeQuery:cvc]];
    return cvc;
}


Solution 1:[1]

For this you would have to subclass UIStoryBoard and override -instantiateViewControllerWithIdentifier:. However there seems to be no way of assigning a class to a storyboard file.

You can however supply dependencies to your controllers via - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender in your view controller.

I think a storyboard is not intended for reuse, it just makes it easier to wire your reusable components together. In terms of OOP, it's not a good solution.

Solution 2:[2]

I have been using the approach shown in this article to do the factory pattern with storyboards:

https://medium.com/ios-os-x-development/safer-uiviewcontroller-creation-when-using-storyboards-1915ac2b2c80#.ebor5maq7

What I really like about this approach, is that you can do dependency injection with storyboards allowing me to pass my dataApi easily between classes.

Also I am no longer having to use prepareWithSegue. Instead I just initialise the view like so:

func didSelectApplication(application: Application) {

    let factory = StoryboardViewControllerFactory(storyboard: UIStoryboard(name: "Main", bundle: nil))
    let applicationController = factory.createApplicationViewController(application, dataApi: dataApi)
    navigationController?.pushViewController(applicationController, animated: true)
}

With prepareForSegue I was unable to pass in the application as an argument, so I had a property on the class. Now I am able to pass it into the method which has eliminated the need for a property on the class. Something I personally prefer.

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 Marius Soutier
Solution 2 pls