Dependency injection 使用带有视图控制器初始值设定项的情节提要

Dependency injection 使用带有视图控制器初始值设定项的情节提要,dependency-injection,storyboard,typhoon,Dependency Injection,Storyboard,Typhoon,我想使用故事板创建名为“child”的视图控制器,因此我定义: - (TyphoonStoryboard *)storyBoard { return [TyphoonDefinition withClass:[TyphoonStoryboard class] configuration:^(TyphoonDefinition* definition) { [definition useInitializer:@selector(storyboardWithName:fac

我想使用故事板创建名为“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:
,这是为情节提要指定的

问题:

  • 可以将视图控制器初始值设定项与故事板一起使用吗?它看起来像否,类似于appDelegate
  • 这是直接从程序集使用故事板的最简单方法吗
  • 如果我有几个故事板,有没有一种方法可以参数化定义故事板?我不想以
    故事板1,故事板2,…,故事板n
    之类的东西结束

  • 提前感谢。

    感谢您对台风的关注

  • 可以将视图控制器初始值设定项与故事板一起使用吗?它看起来像否,类似于appDelegate
  • 不,您不能两次初始化对象(您可以两次调用
    init
    方法,但这很奇怪,不正确,可能是错误的原因)

    从Xib/情节提要创建的每个UIViewController和UIView都使用
    initWithCoder:
    初始化方法

    相反,您可以使用方法注入和注入
    setData:
    或使用属性注入

  • 这是直接从程序集使用故事板的最简单方法吗 不是。最简单的方法是使用plist引导。(在Info.plist中指定初始情节提要名称时)

    查看此处的指南:

    但如果有多个情节提要,则可以在plist中指定initial,在assembly中指定other

  • 如果我有几个故事板,有没有一种方法可以参数化定义故事板?我不想以情节提要1,情节提要2,…,情节提要n之类的东西结束
  • 是的,您可以使用运行时参数功能。 使用运行时参数,您的定义将变为

    - (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]];
            }];
         }];
    }
    
    -(typhonStoryboard*)故事板,名称:(NSString*)名称
    {
    return[typhondefinition with class:[typhonStoryboard class]配置:^(typhondefinition*定义){
    [定义使用初始值设定项:@选择器(故事板,名称:工厂:捆绑:)参数:^(台风方法*初始值设定项){
    
    [initializer injectParameterWith:name];//为了减少情节提要定义的代码,我最终向
    TyphondFinition添加了一个类别,如:

    @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
    

    因为这是在程序集之外,所以它不会注册多次。

    感谢您的及时响应!关于答案:1.完全同意。2.我已经在使用plist,但仍然必须创建一个根VC,其中包含故事板中的VC。3.我尝试过,但在
    validateScope
    sayi中引发异常ng“运行时参数注入仅适用于原型和对象图范围的定义,但为定义:typhonstoryboard”2设置。您是否使用故事板的plist(UIMainstryBoardFile plist键)?在这种情况下,将自动设置根视图控制器。3.正确。您确定此处需要单音吗?由其生成的ViewController已保留情节提要。2.正确,但在我的情况下,根视图控制器是没有情节提要的自定义视图控制器。3.删除单例作用域后,我在
    doRegistrati中收到一个错误在
    “Key”Storyboard with name:“已注册”我认为3中存在错误。这是因为它在程序集中声明,然后从另一个定义调用
    return[self Storyboard with name:@“Storyboard”]
    在同一个组件中。为此添加了功能请求:我假设工厂参数只需传入
    self
    ,是否正确?