Issues with modules' collaboration (Dip 5.0.2)
Closed this issue · 4 comments
Hi, @ilyapuchka !
We are using latest Dip version 5.0.2, modules and auto-injection.
We are trying to understand modules' collaboration but nothing works as we expected.
Here the code of DipRoot.swift:
import Dip
//
// 1 ATTEMPT
// Fails with error:
// Failed to auto-inject property "_settingsWireframe" of type SettingsWireframe.
// No definition registered for type: SettingsWireframe, arguments: (), tag: nil.
//
let dipRoot = DependencyContainer() { root in
Dip.logLevel = .Verbose
mainModule.collaborate(
with: root,
settingsModule
)
settingsModule.collaborate(
with: root,
mainModule
)
}
let mainModule = DependencyContainer() { container in
let mainWireframe = container.register(.singleton) {
MainWireframe()
as MainWireframe
}
let mainViewController = container.register(.weakSingleton) {
MainViewController(nibName: "MainViewController", bundle: nil)
as MainViewController
}
}
let settingsModule = DependencyContainer() { container in
let settingsWireframe = container.register(.singleton) {
SettingsWireframe()
as SettingsWireframe
}
}
//
// 2 ATTEMPT
// Works:
//
let mainModule = DependencyContainer() { container in
Dip.logLevel = .Verbose
let mainWireframe = container.register(.singleton) {
MainWireframe()
as MainWireframe
}
let mainViewController = container.register(.weakSingleton) {
MainViewController(nibName: "MainViewController", bundle: nil)
as MainViewController
}
let settingsWireframe = container.register(.singleton) {
SettingsWireframe()
as SettingsWireframe
}
}
Here the code of Wireframes.swift:
class MainWireframe {
fileprivate let _settingsWireframe = Injected<SettingsWireframe>()
var settingsWireframe: SettingsWireframe? { return _settingsWireframe.value }
}
class SettingsWireframe {
}
Here the code of AppDelegate.swift:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
if let window = window {
let vc = try! mainModule.resolve() as MainViewController
let navigation = UINavigationController()
window.rootViewController = navigation
navigation.isNavigationBarHidden = true
navigation.viewControllers = [vc]
window.backgroundColor = UIColor.white
window.makeKeyAndVisible()
}
return true
}
}
Full error log here:
Failed to auto-inject property "_mainWireframe" of type MainWireframe.
Failed to auto-inject property "_settingsWireframe" of type SettingsWireframe.
No definition registered for type: SettingsWireframe, arguments: (), tag: nil.
Check the tag, type you try to resolve, number, order and types of runtime
arguments passed to `resolve()` and match them with registered factories
for type SettingsWireframe.
fatal error: 'try!' expression unexpectedly raised an error: Failed to auto-inject
property "_mainWireframe" of type MainWireframe.
Failed to auto-inject property "_settingsWireframe" of type SettingsWireframe.
No definition registered for type: SettingsWireframe, arguments: (), tag: nil.
Check the tag, type you try to resolve, number, order and types of runtime
arguments passed to `resolve()` and match them with registered factories
for type SettingsWireframe.:
file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-800.0.46.2/src/swift/stdlib/public/core/ErrorType.swift, line 178
Here is the test project with .Podfile:
dipCollaborationIssuePackage.zip
Workaround is clear for us.
Do not use modules' collaboration.
Split the dependencies into several functions for purpose of clarity.
let dipRoot = DependencyContainer() { container in
Dip.logLevel = .Verbose
registerMyModuleName(container: container)
}
func registerMyModuleName(container: DependencyContainer) {
... register dependencies
}
Hi @sc0rch. The problem may be that your containers are actually never created, except main container. In Swift global static constants are lazy. Here it says:
"The lazy initializer for a global variable (also for static members of structs and enums) is run the first time that global is accessed, and is launched as dispatch_once to make sure that the initialization is atomic. "
And as you have collaboration setup in root container that is never accessed this code is never executed. I would probably create a configure method that would be called from app delegate and that sets up collaboration what will make it to accesses all containers.
Oh, I see. I haven't knew about that.
Thanks for the help, problem has been fixed.