'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:
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 |
