台风:从程序集中检索情节提要时出现异常
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
。有趣的结果是:
- 在 RootViewController 中,
_registry
在我的 ApplicationAssembly 中包含 all 台风定义的列表。即所有对象和故事板定义
- 在 PaymentApproveViewController 中,
_registry
包含所有对象 除了 我的五个故事板。这就是TyphoonComponentFactory.componentForKey找不到故事板时抛出异常的原因。
顺便说一句:rootViewController
和PaymentApproveViewController
中程序集的地址不同。所以注入的是两个不同的程序集。这可以避免吗,还是预期的行为?
看起来问题出在:
[=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
协议。
我正在使用 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
。有趣的结果是:
- 在 RootViewController 中,
_registry
在我的 ApplicationAssembly 中包含 all 台风定义的列表。即所有对象和故事板定义 - 在 PaymentApproveViewController 中,
_registry
包含所有对象 除了 我的五个故事板。这就是TyphoonComponentFactory.componentForKey找不到故事板时抛出异常的原因。
顺便说一句:rootViewController
和PaymentApproveViewController
中程序集的地址不同。所以注入的是两个不同的程序集。这可以避免吗,还是预期的行为?
看起来问题出在:
[=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
协议。