Typhoon using storyboard with view controller initializers
I want to use storyboards to create a view controller named "child", so I define:
- (TyphoonStoryboard *)storyBoard
{
return [TyphoonDefinition withClass:[TyphoonStoryboard class] configuration:^(TyphoonDefinition* definition) {
[definition useInitializer:@selector(storyboardWithName:factory:bundle:) parameters:^(TyphoonMethod *initializer) {
[initializer injectParameterWith:@"Storyboard"];
[initializer injectParameterWith:self];
[initializer injectParameterWith:[NSBundle mainBundle]];
}];
definition.scope = TyphoonScopeSingleton; //Let make this a singleton
}];
}
- (ChildViewController *)childViewControllerFromStoryboard
{
return [TyphoonDefinition withFactory:self.storyBoard selector:@selector(instantiateInitialViewController)];
}
I will have a root view controller which will contain the child view controller
- (RootViewController *)rootViewController {
return [TyphoonDefinition withClass:[RootViewController class] configuration:^(TyphoonDefinition *definition) {
[definition useInitializer:@selector(initWithChildViewController:) parameters:^(TyphoonMethod *initializer) {
[initializer injectParameterWith:self.childViewControllerFromStoryboard];
}];
}];
}
The last part is for injecting dependencies for the child view controller:
- (ChildViewController *)childViewController {
return [TyphoonDefinition withClass:[ChildViewController class] configuration:^(TyphoonDefinition *definition) {
// Initilization doesn't work.
[definition useInitializer:@selector(initWithData:) parameters:^(TyphoonMethod *initializer) {
[initializer injectParameterWith:self.data];
}];
// Property injection does.
// [definition injectProperty:@selector(data)]
}];
}
Super normal, I just use its initializer, but it never gets called. I think because it is initWithCoder:
always used, the one that is for storyboarding.
Questions:
- Can view controller initializers be used with storyboard? It looks like no, like appDelegate.
- Is this the easiest way to use storyboards directly from an assembly?
- If I have multiple storyboards, is there a way to define storyboards parametrically? I don't want to end up with something like
storyBoard1, storyBoard2, ..., storyBoardN
.
Thanks in advance.
source to share
Thanks for your interest in the typhoon!
- Can view controller initializers be used with storyboard? It looks like no, like appDelegate.
No, you cannot initialize an object twice (you can call a method twice init
, but it is odd and incorrect and may cause errors).
Every UIViewController and UIView created from Xib / Storyboard uses an initialization method initWithCoder:
.
Instead, you can use method injection and inject setData:
or use property injection.
- Is this the easiest way to use storyboards directly from an assembly?
Not. The easiest approach is to use the self-tuning plist. (When the starting name of the storyboard is specified in Info.plist)
Check out the guide here:
But if you have another storyboard, you can specify an initial value in the plist and another in the assembly.
- If I have multiple storyboards, is there a way to define storyboards parametrically? I don't want to end up with something like storyBoard1, storyBoard2, ..., storyBoardN.
Yes, you can use the runtime arguments typhoon function for that. Using runtime arguments, your definition becomes
- (TyphoonStoryboard *)storyBoardWithName:(NSString *)name
{
return [TyphoonDefinition withClass:[TyphoonStoryboard class] configuration:^(TyphoonDefinition* definition) {
[definition useInitializer:@selector(storyboardWithName:factory:bundle:) parameters:^(TyphoonMethod *initializer) {
[initializer injectParameterWith:name]; // <-- runtime argument injection
[initializer injectParameterWith:self];
[initializer injectParameterWith:[NSBundle mainBundle]];
}];
}];
}
Is this what you are asking for?
source to share
To reduce the code for storyboard definitions, I add a category to TyphoonDefinition
like:
@implementation TyphoonDefinition (Storyboard)
+ (TyphoonStoryboard *)withStoryboardName:(NSString *)storyboardName factory:(TyphoonComponentFactory *)factory
{
return [TyphoonDefinition withClass:[TyphoonStoryboard class] configuration:^(TyphoonDefinition* definition) {
[definition useInitializer:@selector(storyboardWithName:factory:bundle:) parameters:^(TyphoonMethod *initializer) {
[initializer injectParameterWith:storyboardName];
[initializer injectParameterWith:factory];
[initializer injectParameterWith:[NSBundle mainBundle]];
}];
definition.scope = TyphoonScopeSingleton; //Let make this a singleton
}];
}
@end
Since it is outside the assembly, it does not register more than once.
source to share