When using a hand made container/injector responsible for creating and managing the lifecycle of the objects in my graph I use the following pattern(I read in an article about DIY DI in ObjC):
Let's say we have a root view controller that wants to present another one(let's call it detail view controller) passing some data to it. What I normally do is to inject a provider block that takes the data as an argument and returns a new view controller to present. Here is some code...
@implementation RootViewController
{
UIViewController (^detailViewControllerProvider)(SomeData *someData);
}
- (id) initWithDetailViewControllerProvider:(UIViewController (^)(SomeData *someData))detailViewControllerProvider
{
//...
_detailViewControllerProvider = detailViewControllerProvider;
//...
}
// ...
- (void) presentDetailViewControllerWithData:(SomeData *)someData
{
UIViewController *detailViewController = _detailViewControllerProvider(someData);
[self presentViewController:detailViewController animated:YES completion:nil];
}
@end
I could use a factory class as well but this way I avoid creating a new class just creating the provider block in my container class.
The problem comes when I want to use Typhoon as a DI container. How can I use the same pattern? In my detail view controller I am injecting other things and I want to keep using constructor injection, and prefer if it is created by the component factory, not by me. I could create a factory class to create the detail VC, injecting in it(the factory) the dependencies I want to inject later in my detail VC, but it seems too much work comparing to the block based solution.
I don't want to access my component factory from the root view controller and neither use setter injection for someData.
Is there any solution for this?
To inject the TyphoonComponentFactory:
- (void)typhoonSetFactory:(id)theFactory
in your class.self
In any either case, any of your
TyphoonAssembly
interfaces can pose in front of the factory. So for example if you have an assembly calledNetworkAssembly
, you can define a property of typeNetworkAssembly
and inject the factory as that. The documentation for this feature is here.You can use this approach to roll your own factory that:
Typhoon Factories w/ Runtime Arguments:
Your
TyphoonAssembly
interfaces can now implement the above pattern:Example:
And now resolve the component:
The documentation for this feature is here.