Support @MainActor-isolated initializers in factory/singleton registrations
Problem
WhoopDIKit's factory closures are stored and called with no actor context, so Swift 6 strict concurrency rejects registering any type with a @MainActor-isolated init.
This comes up with patterns like:
@MainActor
public protocol AsyncViewModel { ... }
@MainActor
final class MyViewModel: AsyncViewModel {
init(service: MyService) { ... } // implicitly @MainActor
}
Registering this fails to compile:
final class MyModule: DependencyModule {
override func defineDependencies() {
factory {
// ❌ Main actor-isolated initializer cannot be referenced from a non-isolated context
MyViewModel(service: try self.get())
}
}
}
Workarounds
nonisolated init — Swift 6
If the init only sets stored properties, nonisolated is safe. @MainActor isolation applies to methods on self after init, not to setting stored properties.
@MainActor
final class MyViewModel: AsyncViewModel {
nonisolated init(service: MyService) {
self.service = service
}
}
Inject a factory closure — Swift 6
Register a @MainActor () -> MyViewModel instead of the type directly.
WhoopDI resolves dependencies; you construct on the main actor at the call
site.
// Module
factory {
let service: MyService = try self.get()
return { @MainActor in MyViewModel(service: service) } as (@MainActor ()
-> MyViewModel)
}
// @MainActor call site
let makeVM: @MainActor () -> MyViewModel = WhoopDI.inject()
let vm = makeVM()
Swift 5 language mode
Without strict concurrency enabled, this compiles and works fine at runtime as long as inject is always called from the main thread
Support
@MainActor-isolated initializers in factory/singleton registrationsProblem
WhoopDIKit's factory closures are stored and called with no actor context, so Swift 6 strict concurrency rejects registering any type with a
@MainActor-isolatedinit.This comes up with patterns like:
Registering this fails to compile:
Workarounds
nonisolated init— Swift 6If the
initonly sets stored properties,nonisolatedis safe.@MainActorisolation applies to methods onselfafter init, not to setting stored properties.Inject a factory closure — Swift 6
Register a
@MainActor () -> MyViewModelinstead of the type directly.WhoopDI resolves dependencies; you construct on the main actor at the call
site.
Swift 5 language mode
Without strict concurrency enabled, this compiles and works fine at runtime as long as
injectis always called from the main thread