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

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

以防万一,我还通过property方法注入了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

一次(第二次初始化后),self.assembly为零。
AcceptDisclaimerAppInfoModule *disclaimer = [[self.assembly applicationInformationModuleAssembly] acceptDisclaimerModule];

[disclaimer launchModuleFromWindow:self.window];

[self.window makeKeyAndVisible];
return YES;

}

最佳答案

在网上浏览并疯狂思考了这个问题之后,我得出了一些结论。

问题的根源在于Typhoon和我的main.m入口点没有以任何形式同步。因此,main.m调用UIApplicationMain(),参数之一是一个字符串,用于指定所需的id<UIApplicationDelegate>的类型。我从未见过与这种模式有任何偏差,所以我不愿意改变它。

因此,假设不会通过id<UIApplicationDelegate>以“内置”于框架的方式构造Typhoon。尽管您可以执行以下任一操作,但我不建议任何操作:它们似乎都是错误的。

  • 直接从应用程序委托
  • 实例化根TyphoonAssembly的实例
  • 创建一个单例IContainer对象,该对象可以拥抱在启动
  • 时创建的TyphoonAssembly实例
  • 以有害的方式将类别与关联的对象一起使用

  • 问题是……在某个时候,无论您做得如何,您都将需要做这些邪恶的事情之一。

    原因是... Typhoon显然是为在“对象图”的上下文中工作而设计的,因此整个TyphoonAssembly和任何连接的程序集都可以视为图的网。上网之后,您就可以了-您可以从那里接单。您只需要进入...

    因此,我决定执行以下操作:
  • 为我称为IContainer的相关对象的每个“对象图”创建接口,即使它们跨越多个程序集或小于一个程序集。这将Typhoon的思想与IContainer断开了联系,并且可以通过在适当的位置替换一个模拟的Typhoon来进行调试而不使用IContainer
  • 仅在一种非常值得注意的情况下(我刚才提到的一种应用程序委托),独家使用构造函数注入。在那里,使用属性注入仅注入一个属性-所讨论的IContainer
  • 每当您使用属性注入时,您也可能只注入一个属性IContainer,因为您已经破坏了封装并且还可以使自己变得容易。
  • 实现一些有趣的事情,以向自己证明Typhoon的默认范围可以按照您认为的方式起作用。每当我在同一对象图中检测到对任何构造函数的多次调用时,便实现了一些“警报”。
  • id<nonatomic, weak>用于代表类型,而不是像过去一年那样使用id<nonatomic, assign>。关于Typhoon的幕后工作方式,必须使它不断地被委托释放。
  • 使用PList注入和Assembly Composition。例如:

  • 在您的Info.plist中,添加一个名为TyphoonInitialAssemblies的键,其键类型为Array,其值是程序集的类名。但...

    别忘了做另一半,这是确保您有一个像RootAssembly这样的“根”程序集,然后是一些由ModuleAssembly存储的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
    

    在这种情况下,您的Info.plist将具有:
  • TyphoonInitialAssemblies(Array)
  • SubAssemblyA
  • SubAssemblyB
  • 10-04 17:59