2015-07-20 3 views
3

я не могу получить свойства впрыскивается в контроллерах просмотреть с помощью XIBs с initWithNibName:bundle:Typhoon не инъекционного свойство (без раскадровки)

Пример:

Это моя сборка:

@implementation AppAssembly 

- (ViewControllerC *)viewControllerC 
{ 
    return [TyphoonDefinition withClass:[ViewControllerC class] 
          configuration:^(TyphoonDefinition *definition) { 
     [definition injectProperty:@selector(name) with:@"Injected string"]; 
    }]; 
} 

@end 

ViewControllerA код:

@implementation ViewControllerA 

- (IBAction)buttonAction:(id)sender 
{ 
    ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNibName:@"ViewControllerB" bundle:nil]; 
    [self.navigationController pushViewController:viewControllerB animated:YES]; 
} 

@end 

ViewControllerB код:

@implementation ViewControllerB 

- (IBAction)buttonAction:(id)sender 
{ 
    ViewControllerC *viewControllerC = [[ViewControllerC alloc] initWithNibName:@"ViewControllerC" bundle:nil]; 
    [self.navigationController pushViewController:viewControllerC animated:YES]; 
} 

@end 

ViewControllerC код:

@interface ViewControllerC : UIViewController 

@property (copy, nonatomic) NSString *name; 

@end 

@implementation ViewControllerC 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // Why is this not being injected? 
    self.title = self.name; 
} 

@end 

AppDelegate код:

@implementation AppDelegate 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    ViewControllerA *rootViewController = [[ViewControllerA alloc] initWithNibName:@"ViewControllerA" bundle:nil]; 
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController]; 

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    self.window.rootViewController = navigationController; 
    [self.window makeKeyAndVisible]; 

    return YES; 
} 

@end 

Я уже проверил образцы, и они отличаются от такого подхода. Пожалуйста, скажите мне, что я делаю неправильно?

Спасибо.

ответ

1

Тайфун - это инъекция зависимости контейнер, что означает, что он не инструмент, не swizzle или не прикасайтесь к вашим классам. Поэтому, чтобы получить экземпляр класса с введенными зависимостями, , мы должны спросить «Тайфун».

Почему не для раскадровки?

При использовании интеграции plist Typhoon регистрирует TyphoonStoryboard вместо UIStoryboard, чтобы испускать экземпляры на основе определений в раскадровке - работает так же, как и обычная раскадровка с добавленной выгодой, которую вводят зависимости.

В других местах, чтобы получить экземпляры с введенными зависимостями, мы используем интерфейс сборки и задаем Typhoon.

Решение Шаги:

Добавить определение для ViewControllerB в сборке. (В Objective-C вы также можете использовать макросы для автоматической инъекции, если хотите).

- (ViewControllerB *)viewControllerB 
{ 
    return [TyphoonDefinition withClass:[ViewControllerB class] 
     configuration:^(TyphoonDefinition *definition) { 

     [definition useInitializer:@selector(initWithNibName:bundle:) 
      parameters:^(TyphoonMethod *initializer) { 

      [initializer injectParameterWith:@"ViewControllerB"]; 
      [initializer injectParameterWith:[NSBundle mainBundle]]; 
     }]; 

     [definition injectProperty:@selector(assembly) with:self]; 
    }]; 
} 

Добавить недвижимость ViewControllerB:

//Start with this, next task is to back this with a protocol 
@property(nonatomic, strong) AppAssembly *assembly; 

Теперь измените действие на кнопку, которая инстанцирует ViewControllerC:

ViewControllerC *viewControllerC = self.assembly.viewControllerC 
[self.navigationController pushViewController:viewControllerC animated:YES]; 

Теперь мой класс приложений зависит от моего TyphoonAssembly , что, если я этого не хочу?

Все сборки Typhoon могут поддерживаться протоколом, так что ваше приложение видит только поставщика экземпляров, а не тайфуна.Если вы когда-либо хотели мигрировать из Typhoon, просто обеспечите альтернативную реализацию этого протокола - у вас все еще будет надежная архитектура.

+0

Извините, но этот код не компилируется. В вашем примере вы добавляете определение для ViewControllerB и устанавливаете для использования инициализатора с «ViewControllerC» nib, это нормально? Помните, что моя проблема заключается в том, что я хочу ввести свойство 'name' в ViewControllerC при нажатии от B до C. – fernandospr

+0

Извините, я просто набрал его быстро в StackOverflow - я думал, этого может быть достаточно, чтобы вы могли получить картину. Я отредактировал его сейчас. Если что-то неясно, сообщите мне, какая часть. , , Да, когда вы нажимаете «B» на «C», если вы хотите, чтобы вложенные зависимости были введены, вы должны спросить «Тайфун» для «C» –

+0

@fernandospr. Проверяли только, есть ли у вас проблемы, и заметили, что после редактирования (Я думал), ответ ничего не изменился (он не должен был спасти). Я снова редактировал. Извиняюсь за это. –

0

Итак, я должен был сначала спросить мой AppAssembly для экземпляра viewControllerB с инсертом сборки, а затем я смог использовать его для получения экземпляра viewControllerC.

AppAssembly код:

- (ViewControllerB *)viewControllerB 
{ 
    return [TyphoonDefinition withClass:[ViewControllerB class] 
          configuration:^(TyphoonDefinition *definition) { 
           [definition useInitializer:@selector(initWithNibName:bundle:) 
               parameters:^(TyphoonMethod *initializer) { 
                [initializer injectParameterWith:@"ViewControllerB"]; 
                [initializer injectParameterWith:nil]; 
               }]; 

           [definition injectProperty:@selector(assembly) with:self]; 
          }]; 
} 

- (ViewControllerC *)viewControllerC 
{ 
    return [TyphoonDefinition withClass:[ViewControllerC class] 
          configuration:^(TyphoonDefinition *definition) { 
           [definition useInitializer:@selector(initWithNibName:bundle:) 
               parameters:^(TyphoonMethod *initializer) { 
                [initializer injectParameterWith:@"ViewControllerC"]; 
                [initializer injectParameterWith:nil]; 
               }]; 

           [definition injectProperty:@selector(name) with:@"Injected string"]; 
    }]; 
} 

ViewControllerA код:

@implementation ViewControllerA 

- (IBAction)buttonAction:(id)sender 
{ 
    ViewControllerB *viewControllerB = [[[AppAssembly new] activate] viewControllerB]; 
    [self.navigationController pushViewController:viewControllerB animated:YES]; 
} 

@end 

ViewControllerB код:

@implementation ViewControllerB 

- (IBAction)buttonAction:(id)sender 
{ 
    ViewControllerC *viewControllerC = [self.assembly viewControllerC]; 
    [self.navigationController pushViewController:viewControllerC animated:YES]; 
} 

@end 

ViewControllerC код:

@implementation ViewControllerC 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.title = self.name; 
} 

@end 

Как вы можете видеть, я должен был это сделать: ViewControllerB *viewControllerB = [[[AppAssembly new] activate] viewControllerB]; Не уверен, есть ли другой способ. Из-за этого я смог установить сборку в ViewControllerB, и это позволило мне сделать это: ViewControllerC *viewControllerC = [self.assembly viewControllerC]; Однако я заметил, что я мог бы также сделать ViewControllerC *viewControllerC = [[[AppAssembly new] activate] viewControllerC];, поэтому не уверен, что лучший подход. Во всяком случае, я думаю, мне нужно было вызвать новое и активировать хотя бы один раз.

Спасибо.

+0

@Jasper Blues любые мысли по этому поводу? – fernandospr

Смежные вопросы