Search code examples
iosdependency-injectiontyphoon

Typhoon Inject Property to a new object


I am start to use DI containers on iOS and I don't have idea how to inject property in this case:

Imagine we have:

Assembly.m

- (ClassA *)classA {
    return [TyphoonDefinition withClass:[ClassA class] configuration:^(TyphoonDefinition *definition) {
        [definition injectProperty:@selector(url) with:@"http://inject:URL"];
    }];
}

And two classes

ClassA

@interface ClassA : NSObject
@property (nonatomic,readwrite) NSString *url;
@end

ClassB

@interface ClassB : ClassA
@end

And

ViewController.m

@interface ViewController ()
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];

   ClassB *cB = [ClassB new]; 
    NSLog(@"%@",cB.url);
}

I want to where I create new object by ClassB, all objects has injection with url property from my DI container (assembly) Yes I can add property to my ViewController and this injection works fine, but I need inject property to new object.

Maybe I don't understand all principles but I should ask. Thx


Solution

  • Try this.

    - (id)classAObject{
        return [TyphoonDefinition withClass:[ClassA class]
                              configuration:^(TyphoonDefinition *definition){
                                  [definition injectProperty:@selector(url) with:@"http://inject:URL"];
                              }];
    }
    
    - (id)classBObject{
        return [TyphoonDefinition withParent:[self classAObject] class:[ClassB class]];
    }
    
    KSTTestAssembly *assembly = [[KSTTestAssembly alloc] init];
    [assembly activate];
    
    id classB = [assembly classBObject];
    

    Bootstrapping Typhoon

    You can bootstrap Typhoon, and hold a reference to it, Typically in the AppDelegate. In other parts of the application, we don't want to obtain an instance of Typhoon directly:

    • We're coupling our application directly to Typhoon
    • This is not dependency injection, difficult to test, etc

    So what we do instead is:

    • Inject the assembly (or one of the assemblies, in a modular set-up) into the class where we need it. Once an assembly is activated, this will actually be an instance of TyphoonComponentFactory posing as an assembly.

    • It will serve as a factory for emitting a built object graph.

    • Typhoon's default scope is ObjectGraph. So, we don't hold any objects in memory - just recipes for building them. The object graph is instantiated just when we need it.
    • In this way we can proceed from one object graph to another efficiently, and in a loosely coupled way.

    Example:

    - (RootViewController *)rootController
    {
        return [TyphoonDefinition withClass:[RootViewController class] 
        configuration:^(TyphoonDefinition* definition) {
            [definition injectProperty:@selector(assembly)];
        }];
    }
    

    The documentation for this feature is here.

    Storyboards:

    If you like to use story boards and Objective-C, you can use auto-injection macros on your view controllers.