Search code examples
iosswiftswiftuiswinject

Swinject Dependencies not being properly initialized: Swinject: Resolution failed


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:

DIController.swift:

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)
        }
    }
}

MyApp.swift

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)!)
        }
    }
}

Solution

  • 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.