Search code examples
iosxcodeios8typhoon

Typhoon - using one component factory throughout the application


I am configuring the Initial Assemblies in the plist, which are used to instantiate the first controller in the storyboard.

later in the app i am changing the root view controller using:

 TyphoonStoryboard* storyboard = [TyphoonStoryboard storyboardWithName:storyboardType factory:factory bundle:nil];
 UIViewController* newRootView = [storyboard instantiateViewControllerWithIdentifier:identifier];
 self.window.rootViewController = newRootView;

I would like to use the same assemblies when instantiating the new view controller. The reason is that i want the Singletons to remain Singletons. If the assemblies/factory changes all classes are created again, including singletons.

How can i get the factory used to initialize the first view controller in the storyboard?


Solution

  • Tight Storyboard Integration:

    As long as plist integration is used, along with the usual UILaunchStoryboardName and UIMainStoryboardFile, then Typhoon will ensure that any Storyboard is a TyphoonStoryboard. Use exactly as with a normal storyboard, with the added benefit that dependencies will be injected according to the definitions in your TyphoonAssembly classes.

    The TyphoonComponentFactory will be retained by the storyboard and so will persist throughout the lifecycle of your app.


    Outside of Storyboards: (ie MacOS apps, utilities, etc)

    The TyphoonComopnentFactory is indeed designed to be retained throughout the full life-cycle of your app. (Although you could do something else if you wished).

    Key concept:

    • You can use the TyphoonComponentFactory as is.
    • Also, any of your assembly interfaces can pose in front of the TyphoonComponentFactory. At build-time an assembly returns definitions. At run-time it returns built components.

    There are two ways to retain the TyphoonComponentFactory when proceeding from one object-graph to another. We call this making of your components 'Typhoon aware'.


    Approach 1: Inject the assembly:

    - (MyAppDelegate *)appDelegate
    {
        return [TyphoonDefinition withClass:[MyAppDelegate class] 
            configuration:^(TyphoonDefinition *definition)
        {
            //Other injections . . . 
            [definition injectProperty:@selector(factory) with:self];
        }];
    }
    

    The above example injects the TyphoonComponentFactory into a property called factory.

    • When you inject the assembly it can be used as a TyphoonComponentFactory.
    • It can also be used as any of your assembly types. For example, you could declare a property components of type CoreCompopnents and inject the assembly as that.

    More info on this feature can be found in the User Guide here.


    Approach 2: Use callback hook:

    Another way of making a component 'Typhoon aware' is to use Typhoon's callback hooks. by overriding NSObject category methods:

    typhoonSetFactory:(id)thefactory
    

    As with the other approach above, the factory can be used as a TyphoonComponentFactory or any of your assembly interfaces my pose in front, both of the following are fine:

    typohoonSetFactory:(TyphoonComponentFactory*)factory
    {
        //Do something with factory
    }
    
    typhoonSetFactory:(ApplicationAssembly*)assembly
    {
        //Do something with assembly
    }
    

    Of the two approaches, use the one that suits you best. We recommend the former, as it 'non-invasive' meaning your own classes don't directly call any Typhoon APIs. If you ever wished to migrate away from Typhoon, you would simply provide an alternative implementation of the assembly.



    Proceeding from one object graph to another:

    Once a component is 'Typhoon aware' using either of the above methods, we can use this to proceed from one object graph to another.

    • The default scope for Typhoon is TyphoonScopeObjectGraph, meaning you can load a view controller, including any delegates and circular references. Upon completion, it will be discarded from memory.
    • Meanwhile any components of TyphoonScopeSingleton (or TyphoonScopeWeakSingleton) will be retained.

    More information on this feature is in the User Guide here.


    Proceeding from one story board to another:

    To programmatically instantiate a new storyboard at some point in your app (eg a view controller):

    UIStoryboard *board = [TyphoonStoryboard storyboardWithName:@"name" 
        factory:factory bundle:[NSBundle mainBundle]];
    

    . . obtain the factory using Approach 1 or Approach 2 above.



    Summary:

    • The assembly follows normal Objective-C/Swift memory rules. So as long as its being used by at least one of your classes, it will continue to persist. Using the process of 'proceeding from one object graph to another' described above means that it will persist throughout the life-cycle of your app.