台风:从程序集中检索情节提要时出现异常

Typhoon: Exception when retrieving storyboard from assembly

我正在使用 Typhoon 进行依赖注入。但我有一个问题。偶尔,我会遇到以下异常:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'No component matching id 'nemIdStoryboard'.'

发生此异常的代码如下所示:

class PaymentApproveViewController : UIViewController {
   var assembly : ApplicationAssembly!
   //...
   private func signPayment() {
      let storyboard = assembly.nemIdStoryboard()
      let controller = storyboard.instantiateInitialViewController() as NemIDViewController
   //...
   }
}

我的汇编代码是这样的:

public dynamic func rootViewController() -> AnyObject {
    return TyphoonDefinition.withClass(RootViewController.self) {
        [=12=].injectProperty("assembly", with: self)
    }
}

public dynamic func paymentApproveViewController() -> AnyObject {
    return TyphoonDefinition.withClass(PaymentApproveViewController.self) {
        [=12=].injectProperty("assembly", with: self)
    }
}
public dynamic func nemIdStoryboard() -> AnyObject {
    return TyphoonDefinition.withClass(TyphoonStoryboard.self) {
        [=12=].useInitializer("storyboardWithName:factory:bundle:") {
            [=12=].injectParameterWith("NemID")
            [=12=].injectParameterWith(TyphoonBlockComponentFactory(assembly:self))
            [=12=].injectParameterWith(nil)
        }
    }
}

我有完全相同的代码将程序集注入我的 RootViewController,它还检索故事板并以与上述相同的方式实例化视图控制器。但这永远不会失败。

我无法确定为什么这会偶尔失败并且不一致的任何原因。但我有一种感觉,程序集可能无法在使用可选类型的 Swift 代码中正确初始化。难道是这样吗?或者你能建议我做些什么来使这段代码工作吗?

编辑:

我已经从 rootViewController 和 PaymentApproveViewController 打印出 TyphoonComponentFactory._registry。有趣的结果是:

顺便说一句:rootViewControllerPaymentApproveViewController 中程序集的地址不同。所以注入的是两个不同的程序集。这可以避免吗,还是预期的行为?

看起来问题出在:

[=10=].injectParameterWith(TyphoonBlockComponentFactory(assembly:self))

这是仅使用在当前程序集中找到的定义来实例化一个新程序集,并跳过任何协作程序集。你实际上想要:

[=11=].injectParameterWith(self)

在 Objective-C 中,可以将任何 TyphoonAssembly 转换为 TyphoonComponentFactory(在运行时,您的程序集只是 TyphoonComponentFactory 的一个实例,在任何情况下都冒充程序集) .使用 Swift 的严格类型检查这是不可能的,因此 Typhoon 3.0 具有 TyphoonAssembly class 符合 TyphoonComponentFactory 协议,所以如果你需要来自这个接口的任何方法,它们是可用的。例如:

assembly.componentForType(SomeType.self)

总结

  • 在 Swift 中我们只注入 TyphoonAssembly 而不是 TyphoonComponentFactory.
  • TyphoonAssembly 符合 TyphoonComponentFactory 协议。