Тайфун с использованием раскадровки с инициализаторами контроллера вида

Я хочу использовать раскадровки для создания контроллера представления с именем "child", поэтому я определяю:

- (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's make this a singleton
    }];
}

- (ChildViewController *)childViewControllerFromStoryboard
{
    return [TyphoonDefinition withFactory:self.storyBoard selector:@selector(instantiateInitialViewController)];
}

У меня будет корневой контроллер вида, который будет содержать дочерний контроллер вида

- (RootViewController *)rootViewController {
    return [TyphoonDefinition withClass:[RootViewController class] configuration:^(TyphoonDefinition *definition) {
        [definition useInitializer:@selector(initWithChildViewController:) parameters:^(TyphoonMethod *initializer) {
            [initializer injectParameterWith:self.childViewControllerFromStoryboard];
        }];
    }]; 
}

Последняя часть просто для того, чтобы ввести зависимости для дочернего контроллера вида:

- (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)]
    }];
}

Супер нормально, я просто использую его инициализатор, но он никогда не вызывается. Я думаю это потому что initWithCoder: всегда используется, тот, который предназначен для раскадровки.

Вопросы:

  1. Можно ли использовать инициализаторы контроллера представления с раскадровками? Похоже, нет, похоже на appDelegate.
  2. Это самый простой способ использовать раскадровки прямо из сборки?
  3. Если у меня есть несколько раскадровок, есть ли способ определить раскадровки параметрически? Я не хочу закончить с чем-то вроде storyBoard1, storyBoard2, ..., storyBoardN,

Заранее спасибо.

2 ответа

Решение

Спасибо за ваш интерес к Тайфуну!

  1. Можно ли использовать инициализаторы контроллера представления с раскадровками? Похоже, нет, похоже на appDelegate.

Нет, вы не можете инициировать объект дважды (вы можете вызвать init метод дважды, но он странный и неправильный и может быть причиной ошибок).

Каждый UIViewController и UIView, созданные из Xib/Storyboard, используют initWithCoder: метод инициализации.

Вместо этого вы можете использовать метод инъекций и инъекций setData: или использовать свойство инъекции.

  1. Это самый простой способ использовать раскадровки прямо из сборки?

Нет. Самый простой подход - это использование plst начальной загрузки. (Когда начальное имя раскадровки указано в Info.plist)

Проверьте руководство здесь:

https://github.com/typhoon-framework/Typhoon/wiki/Obtaining-Built-Components

Но если у вас есть более одной раскадровки, вы можете указать начальный в листе, а другой в сборке.

  1. Если у меня есть несколько раскадровок, есть ли способ определить раскадровки параметрически? Я не хочу в конечном итоге что-то вроде storyBoard1, storyBoard2, ..., storyBoardN.

Да, для этого вы можете использовать функцию тайфуна аргументов во время выполнения. Используя аргументы времени выполнения, ваше определение становится

- (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]];
        }];
     }];
}

Это то, что вы просите?

Чтобы уменьшить код для определений раскадровки, я добавляю категорию к TyphoonDefinition лайк:

@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's make this a singleton
    }];
}

@end

Поскольку это вне сборки, оно регистрируется не более одного раза.

Другие вопросы по тегам