2

我正在使用 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) {
        $0.injectProperty("assembly", with: self)
    }
}

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

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

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

编辑:

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

  • 在 RootViewController 中,_registry包含我的 ApplicationAssembly 中所有台风定义的列表。即所有对象和情节提要定义
  • 在 PaymentApproveViewController 中,包含我的五个故事板之外的_registry所有对象。这就是 TyphoonComponentFactory.componentForKey 在找不到情节提要时抛出异常的原因。

顺便说一句:程序集的地址在rootViewController和中不同PaymentApproveViewController。所以注入的是两个不同的程序集。可以避免这种情况,还是预期的行为?

4

1 回答 1

2

看起来问题出在:

$0.injectParameterWith(TyphoonBlockComponentFactory(assembly:self))

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

$0.injectParameterWith(self)

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

assembly.componentForType(SomeType.self)

概括

  • 在 Swift 中,我们只注入TyphoonAssemblynot TyphoonComponentFactory
  • TyphoonAssembly符合TyphoonComponentFactory协议。
于 2015-03-18T10:37:48.010 回答