What is the proper way to inject a UIViewController instantiated from a UIStoryboard using Typhoon and swift?
I can't find any clear examples of this in either of the sample apps, and when I translate the Objective C code from the documentation it throws an exception.
Below is the code from my AppAssembly:
public dynamic func loginViewController() -> LoginViewController {
return TyphoonDefinition.withClass(LoginViewController.self) {
(definition) in
definition.injectProperty("socialClient",with:self.coreComponents.socialClient())
//definition.scope = TyphoonScope.Singleton
} as LoginViewController
}
And this is the exception that gets thrown:
0x10636ca1c: jne 0x10636ca10 ; swift_dynamicCastClassUnconditional + 48
0x10636ca1e: leaq 0x36b3d(%rip), %rax ; "Swift dynamic cast failed"
0x10636ca25: movq %rax, 0xb4a2c(%rip) ; gCRAnnotations + 8
0x10636ca2c: int3
0x10636ca2d: movq %rdi, %rax
0x10636ca30: popq %rbp
0x10636ca31: retq
0x10636ca32: nopw %cs:(%rax,%rax)
The "Swift dynamic cast failed" leads me to believe that what was possible using Objective C is just not possible using Swift.
Has anyone been able to make this work? Any assistance would be greatly appreciated. The library looks really nice and I really want to use it.
The following rules apply using Typhoon in both Swift and Objective-C:
However there's an important difference between Typhoon Objective-C and Typhoon Swift:
Objective-C:
TyphoonComponentFactory
simply by casting it to one of your assembly interfaces. Swift:
AnyObject
. Swift's strict type-checking won't allow otherwise. This is shown in the Quick Start guide for Swift. TyphoonComponentFactory
to one of the assembly interfaces. However its still possible to inject the assembly into a component as follows: Injecting the Assembly:
dynamic func appDelegate() -> AnyObject {
return TyphoonDefinition.withClass(AppDelegate.self) {
(definition) in
//The type of this property can be TyphoonComponentFactory or any of your
//assembly interfaces.
definition.injectProperty("assembly", with: self)
}
}
Fixing your crash:
Therefore to fix the crash by obeying the above conditions, change your code to the following:
Change your code to the following:
public dynamic func loginViewController() -> AnyObject {
//etc
}
Resolving Components from Storyboard:
As long as your start Typhoon using plist integration and include the usual UILaunchStoryboardName
and UIMainStoryboardFile
, then Typhoon will ensure your storyboard is an instance of TyphoonStoryboard
, this works like a normal storyboard with the added behavior that dependencies are injected according to rules in your assembly.
Documentation for this feature is here.
The following features will be coming soon:
TyphoonComponentFactory
can't be casted to an assembly interface. (Bootstrapping Typhoon via an app's plist will remain a valid way).