I'm having an issue when trying to initialize my dependencies via a container using Swinject. I get the error:
Swinject: Resolution failed. Expected registration: { Service: LoginViewModel, Factory: Resolver -> LoginViewModel } Available registrations: MyApp/MyApp.swift:29: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Not sure what the issue could be. Any insight would be greatly appreciated.
Here is a simplified version of my code:
import Swinject
import Supabase
class DIContainer {
static let shared = DIContainer()
let container: Container
private init() {
container = Container()
}
func initializeDependencies() async {
container.register(LoginViewModel.self) { resolver in
LoginViewModel(supabaseClient: supabaseClient)
}
}
}
import SwiftUI
import Swinject
import SwiftData
@main
struct MyApp: App {
let persistenceController = PersistenceController.shared
init() {
// Initialize dependencies
Task {
await DIContainer.shared.initializeDependencies()
}
}
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(DIContainer.shared.container.resolve(LoginViewModel.self)!)
}
}
}
You have wrapped your call to DIContainer.shared.initializeDependencies()
in a Task
. This means that it will complete asynchronously.
As a result, the dependencies are not yet registered when you call DIContainer.shared.container.resolve(LoginViewModel.self)
. Since you force unwrap the result of this call you get a crash.
There is no need for initializeDependencies
to be declared async
. Remove this declaration and then you won't need the Task
.
Also, it should be noted that singletons are an anti-pattern in general and a specific anti-pattern that DI is intended to address. It is ironic that you have used a singleton for your DI container. You don't need to do this.