台风使用故事板和视图控制器初始化器

3
我想使用故事板来创建一个名为“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:,这是指定给storyboards的那个。

问题:

  1. 是否可以使用视图控制器的初始化程序与storyboards一起使用?看起来不行,类似于appDelegate。
  2. 这是直接从组件上使用storyboards的最简单方法吗?
  3. 如果我有几个storyboard,有没有一种定义参数化storyboard的方法?我不想最终得到像storyBoard1、storyBoard2、...,storyBoardN这样的东西。

提前感谢。

2个回答

5

感谢您对Typhoon的关注!

  1. 是否可以在故事板中使用视图控制器初始化程序?看起来不行,类似于appDelegate。

不,您不能两次初始化对象(可以调用init方法两次,但这很奇怪、不正确,并可能导致错误)。

从Xib/Storyboard创建的每个UIViewController和UIView都使用initWithCoder:初始化方法。

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

  1. 这是直接从程序集使用storyboards的最简单方法吗?

不是。最简单的方法是使用plist引导程序。(当在Info.plist中指定初始故事板名称时)

请查看此处的指南:

https://github.com/typhoon-framework/Typhoon/wiki/Obtaining-Built-Components#first-bootstrap-typhoon-using-either

但是,如果您有多个故事板,则可以在plist中指定初始故事板,而在程序集中指定其他故事板。

  1. 如果我有几个故事板,是否有一种定义参数化故事板的方法?我不想最终得到像storyBoard1、storyBoard2、...、storyBoardN这样的东西。

是的,您可以使用Typhoon的运行时参数功能来实现。 使用运行时参数,您的定义将变为

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

这是您要求的内容吗?


感谢您的迅速回复!关于答案:
  1. 完全没问题。
  2. 我已经在使用 plist,但仍然需要创建一个根视图控制器,该控制器将包含来自故事板的视图控制器。
  3. 我已经尝试过了,但它会在 validateScope 中引发异常,说“运行时参数注入仅适用于原型和对象图作用域定义,但已设置为定义:TyphoonStoryboard”。
- 7ynk3r
  1. 你是否在使用plist文件来管理Storyboard(UIMainStoryboardFile plist键)?如果是这样,根视图控制器会自动设置。
  2. 正确。你确定你需要在这里使用单例模式吗?Storyboard已经被从中生成的viewControllers保留了。
- Aleksey
  1. 是的,但在我的情况下,根视图控制器是一个没有故事板的自定义视图控制器。
  2. 在删除单例范围后,我在“doRegistration”中收到一个错误:“键'storyboardWithName:'已注册”。
- 7ynk3r
我认为第三个错误是因为它在汇编中声明,然后从同一汇编中的另一个定义“return [self storyboardWithName:@”Storyboard“]”中调用。 - 7ynk3r
是的。在两个程序集方法(或更多)中不能返回相同的定义对象。每个方法必须返回新的定义对象。也许我们应该修复它,因为它可以与运行时参数一起使用。(这是旧异常) - Aleksey
1
已添加该功能请求: https://github.com/typhoon-framework/Typhoon/issues/272 - Aleksey

2
为减少故事板定义中的代码量,我最终添加了一个类别到 TyphoonDefinition 中,如下所示: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

由于这是在程序集之外,它不会被注册超过一次。

我猜你的意思是对于工厂参数,你只需要传入 self 对吗? - fatuhoku

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接