2

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

第二次,重要的时间,它是使用init. 它永远不会获得对程序集的引用。

以防万一,我还注入了assemblyvia 属性方法。不去。

这是代码:

集会

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

应用委托

@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;

}

4

1 回答 1

2

在网上查看并疯狂地思考这个问题后,我得出了一些结论。

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

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

  • TyphoonAssembly直接从您的应用委托实例化您的根实例
  • 创建一个可以拥抱启动时创建的实例的单例IContainer对象TyphoonAssembly
  • 以邪恶的方式使用具有关联对象的类别

问题是......在某些时候,你将需要做这些邪恶的事情之一,不管你做错了什么。

原因是......Typhoon显然设计为在“对象图”的上下文中工作,因此整个TyphoonAssembly和任何连接的程序集都可以被认为是图的网络。一旦你进入网络,你就没事了——你可以从那里拿它。你只需要进去...

所以,我决定这样做:

  1. 为我调用的相关对象的每个“对象图”创建接口IContainer,即使它们跨越多个程序集或者如果它们小于一个程序集。这断开了 的想法,Typhoon并且IContainer可以在不Typhoon替换模拟IContainer的情况下进行调试。
  2. 只使用构造函数注入,除非在一个非常值得注意的情况下——我刚才提到的那个,应用程序委托。在那里,使用属性注入只注入一个属性——有IContainer问题的。
  3. 每当您使用属性注入时,您最好只注入一个属性, the IContainer,因为您已经破坏了封装,您还不如让自己轻松一些。
  4. 实现一些有趣的东西来向自己证明Typhoon默认作用域的工作方式与您认为的一样。每当我检测到对同一对象图中的任何构造函数的多次调用时,我都会实施一些“警报”。
  5. 用于id<nonatomic, weak>委托类型,不像id<nonatomic, assign>我在过去一年中所做的那样。关于幕后工作方式的某些东西Typhoon必须使其不断放开代表。
  6. 使用 PList 注入和程序集组合。一个例子:

在 Info.plist 中,添加一个名为 type 和 values 的键TyphoonInitialAssembliesArray它们是程序集的类名。但...

不要忘记做另一半,这是为了确保你有一个“根”程序集RootAssembly,然后是一些ModuleAssembly由 s 存储的 s 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 将具有:

  1. TyphoonInitialAssemblies( Array)
    • SubAssemblyA
    • SubAssemblyB
于 2015-06-23T07:30:21.557 回答