使用Typhoon Assembly创建的AppDelegate(plist方法)创建两次,属性注入不起作用

时间:2015-06-16 13:16:06

标签: ios objective-c dependency-injection typhoon

我正在尝试使用PList集成方法引导Typhoon,但我的ApplicationDelegate正在创建两次。它第一次创建时,显然是由Typhoon创建的。那个时候,它使用特殊的初始值设定项initWithAssembly:Typhoon将其提供给程序集。

第二次,重要的时间,它是使用init创建的。它永远不会引用程序集。

以防万一,我还通过属性方法注入了assembly。不行。

以下是代码:

装配

- (UIApplication *)sharedApplication {
    return [TyphoonDefinition withClass:[UIApplication class] configuration:^(TyphoonDefinition *definition) {
        [definition useInitializer:@selector(sharedApplication)];
    }];
}

- (CTISApplicationDelegate *)appDelegate {
    return [TyphoonDefinition withClass:[CTISApplicationDelegate class]
                          configuration:^(TyphoonDefinition *definition) {
                              [definition useInitializer:@selector(initWithAssembly:) parameters:^(TyphoonMethod *initializer) {
                                  [initializer injectParameterWith:@(3)];
                              }];

                              definition.scope = TyphoonScopeSingleton;
                          }];
}

的AppDelegate

@property (nonatomic, strong, readwrite) ApplicationAssembly *assembly;

@property (nonatomic, strong, readwrite) UIWindow *window;

- (instancetype)initWithAssembly:(ApplicationAssembly *)assembly;

...

// This gets called once, the first time, and assembly is NOT nil.
- (instancetype)initWithAssembly:(ApplicationAssembly *)assembly {
    self = [super init];

    if (self) {
        self.assembly = assembly;
    }

    return self;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];

// This gets ca

lled一次(在第二次init之后)并且self.assembly为nil。

AcceptDisclaimerAppInfoModule *disclaimer = [[self.assembly applicationInformationModuleAssembly] acceptDisclaimerModule];

[disclaimer launchModuleFromWindow:self.window];

[self.window makeKeyAndVisible];
return YES;

}

1 个答案:

答案 0 :(得分:2)

在网上看到并且有点疯狂地过度思考这个问题后,我得出了一些结论。

问题的根源是2^30和我的Typhoon入口点没有以任何形式同步。因此,main.m调用main.m,其中一个参数是一个字符串,用于指定所需的UIApplicationMain()种类。我从来没有看到任何偏离这种模式,所以我不愿意改变它。

因此,给定id<UIApplicationDelegate>不会通过id<UIApplicationDelegate>以“内置”框架的方式构建。虽然您可以执行以下操作之一,但我不建议:它们似乎都错了。

  • 直接从您的app delegate
  • 实例化您的根Typhoon的实例
  • 创建一个单独的TyphoonAssembly对象,可以拥抱在启动时创建的IContainer实例
  • 以邪恶的方式使用带有关联对象的类别

问题是......在某些时候,如果你做对不对,你将需要做一件这些邪恶的事情。

原因是...... TyphoonAssembly显然是设计用于“对象图”的上下文中,因此整个Typhoon和任何连接的程序集都可以被视为图形网。一旦你进入网络,你很好 - 你可以从那里拿走它。你只需要进入......

所以,我决定这样做:

  1. 为我称为TyphoonAssembly的相关对象的每个“对象图”创建接口,即使它们跨越多个程序集或者小于程序集。这使IContainer的{​​{1}}概念脱离了,并且可以通过替换模拟Typhoon来调试IContainer
  2. 使用构造函数注入 EXCLUSIVELY 除了一个非常值得注意的案例 - 我刚才提到的那个,即app代理。在那里,使用属性注入只注入一个属性 - 问题Typhoon
  3. 每当你使用属性注入时,你也可以只注入一个属性IContainer,因为你已经破坏了封装,你也可以轻松自己。
  4. 实现一些有趣的事情来向自己证明IContainer的默认范围以您认为的方式工作。每当我在同一对象图中检测到对任何构造函数的多次调用时,我都实现了一些“警报”。
  5. 使用IContainer作为代理类型,而不是像过去一年那样Typhoon。关于id<nonatomic, weak>在幕后工作方式的一些事情必须让它不断地让代表们离开。
  6. 使用PList注射和装配成分。一个例子:
  7. 在Info.plist中,添加一个名为id<nonatomic, assign>的密钥,其Typhoon类型和值是程序集的类名。但...

    不要忘记做另一半,这是为了确保你有TyphoonInitialAssemblies之类的“root”程序集,然后是Array存储的一些RootAssembly

    ModuleAssembly

    在这种情况下,您的Info.plist将具有:

    1. RootAssembly@protocol IAppLaunchContainer - (UIWindow *)launchWindow; - (UIViewController *)launchRootViewController; - (UIImageView *)launchImageView; @end @protocol IDefaultUIComponentsContainer - (UIView *)uiDefaultView; - (UILabel *)uiDefaultLabelWithName:(NSString *)name; - (UIButton *)uiDefaultButtonWithTitle:(NSString *)title; @end @interface RootAssembly : TyphoonAssembly<IAppLaunchContainer, IDefaultUIComponentsContainer> @property (nonatomic, strong) SubAssemblyA *thisModuleAssembly; @property (nonatomic, strong) SubAssemblyB *thatModuleAssembly; @end
      • TyphoonInitialAssemblies
      • Array