diff --git a/Sources/InfomaniakDI/InjectService.swift b/Sources/InfomaniakDI/InjectService.swift index da6a4d7..423d58b 100644 --- a/Sources/InfomaniakDI/InjectService.swift +++ b/Sources/InfomaniakDI/InjectService.swift @@ -16,7 +16,8 @@ import Foundation // MARK: - InjectService /// A property wrapper that resolves shared objects when the host type is initialized. -@propertyWrapper public struct InjectService: CustomDebugStringConvertible, Equatable, Identifiable { +@propertyWrapper public struct InjectService: CustomDebugStringConvertible, Equatable, Identifiable, + @unchecked Sendable { /// Identifiable /// /// Something to link the identity of this property wrapper to the underlying Service type. @@ -40,12 +41,11 @@ import Foundation """ } - /// Store the resolved service - var service: Service! + let service: Service - public var container: SimpleResolvable - public var customTypeIdentifier: String? - public var factoryParameters: [String: Any]? + public let container: SimpleResolvable + public let customTypeIdentifier: String? + public let factoryParameters: [String: Any]? public init(customTypeIdentifier: String? = nil, factoryParameters: [String: Any]? = nil, diff --git a/Sources/InfomaniakDI/LazyInjectService.swift b/Sources/InfomaniakDI/LazyInjectService.swift index 0ca695d..4457ace 100644 --- a/Sources/InfomaniakDI/LazyInjectService.swift +++ b/Sources/InfomaniakDI/LazyInjectService.swift @@ -14,7 +14,11 @@ import Foundation /// Inject a service at the first use of the property -@propertyWrapper public final class LazyInjectService: Equatable, Identifiable { +@propertyWrapper public final class LazyInjectService: Equatable, Identifiable, @unchecked Sendable { + private let semaphore = DispatchSemaphore(value: 1) + + var service: Service? + /// Identifiable /// /// Something to link the identity of this property wrapper to the underlying Service type. @@ -38,12 +42,9 @@ import Foundation """ } - /// Store the resolved service - var service: Service? - - public var container: SimpleResolvable - public var customTypeIdentifier: String? - public var factoryParameters: [String: Any]? + public let container: SimpleResolvable + public let customTypeIdentifier: String? + public let factoryParameters: [String: Any]? public init(customTypeIdentifier: String? = nil, factoryParameters: [String: Any]? = nil, @@ -55,16 +56,20 @@ import Foundation public var wrappedValue: Service { get { + semaphore.wait() + defer { semaphore.signal() } + if let service { return service } do { - service = try container.resolve(type: Service.self, - forCustomTypeIdentifier: customTypeIdentifier, - factoryParameters: factoryParameters, - resolver: container) - return service! + let resolvedService = try container.resolve(type: Service.self, + forCustomTypeIdentifier: customTypeIdentifier, + factoryParameters: factoryParameters, + resolver: container) + service = resolvedService + return resolvedService } catch { fatalError("DI fatal error :\(error)") }