From 288c912d86edb171015ec11b123453723bb4d0c9 Mon Sep 17 00:00:00 2001 From: Marek Pridal Date: Fri, 28 Nov 2025 15:06:05 +0100 Subject: [PATCH 1/4] Swift Resolver and Container to MainActor on Darwin platform --- Sources/SwinjectLight/Container.swift | 9 ++++++++- Tests/SwinjectLightTests/SwinjectLightTests.swift | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Sources/SwinjectLight/Container.swift b/Sources/SwinjectLight/Container.swift index 3ad7eff..f073b94 100644 --- a/Sources/SwinjectLight/Container.swift +++ b/Sources/SwinjectLight/Container.swift @@ -1,10 +1,13 @@ import Foundation +#if canImport(Darwin) +@MainActor +#endif public protocol Resolver: AnyObject { func resolve(_ type: Service.Type) -> Service } -public final class Container: @unchecked Sendable { +public final class Container { private var storage: [String: Any] = [:] public init() { } @@ -15,6 +18,10 @@ public final class Container: @unchecked Sendable { } } +#if !canImport(Darwin) +extension Container: @unchecked Sendable { } +#endif + extension Container: Resolver { public func resolve(_ type: Service.Type) -> Service { let key = "\(type)" diff --git a/Tests/SwinjectLightTests/SwinjectLightTests.swift b/Tests/SwinjectLightTests/SwinjectLightTests.swift index 6a0e9f4..ef325b3 100644 --- a/Tests/SwinjectLightTests/SwinjectLightTests.swift +++ b/Tests/SwinjectLightTests/SwinjectLightTests.swift @@ -4,6 +4,9 @@ import XCTest private protocol MockDependency: AnyObject { } private class MockClass: MockDependency { } +#if canImport(Darwin) +@MainActor +#endif final class SwinjectLightTests: XCTestCase { func testRegisterAndResolve() { let container = Container() From a0d9862604d588db6ff81b56a63297d2394e608b Mon Sep 17 00:00:00 2001 From: Marek Pridal Date: Fri, 28 Nov 2025 15:10:38 +0100 Subject: [PATCH 2/4] Add TODO --- Sources/SwinjectLight/Container.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/SwinjectLight/Container.swift b/Sources/SwinjectLight/Container.swift index f073b94..04a8dc6 100644 --- a/Sources/SwinjectLight/Container.swift +++ b/Sources/SwinjectLight/Container.swift @@ -18,6 +18,8 @@ public final class Container { } } +// TODO: MP + #if !canImport(Darwin) extension Container: @unchecked Sendable { } #endif From 42b36126600155358db08675bf37ced27a28e43c Mon Sep 17 00:00:00 2001 From: Marek Pridal Date: Fri, 28 Nov 2025 15:27:47 +0100 Subject: [PATCH 3/4] Implement support for passing parameters into resolve --- Sources/SwinjectLight/Container.swift | 19 +++++++++++-- .../SwinjectLightTests.swift | 28 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Sources/SwinjectLight/Container.swift b/Sources/SwinjectLight/Container.swift index 04a8dc6..9d62e42 100644 --- a/Sources/SwinjectLight/Container.swift +++ b/Sources/SwinjectLight/Container.swift @@ -16,9 +16,12 @@ public final class Container { let key = "\(type)" storage[key] = factory } -} -// TODO: MP + public func register(_ type: Service.Type, parametersType: Parameters.Type, factory: @escaping (Resolver, Parameters) -> Service) { + let key = "\(type)" + storage[key] = factory + } +} #if !canImport(Darwin) extension Container: @unchecked Sendable { } @@ -36,4 +39,16 @@ extension Container: Resolver { let service = typedFactory?(self) return service! } + + public func resolve(_ type: Service.Type, parameters: Parameters) -> Service { + let key = "\(type)" + guard let factory = storage[key] else { + fatalError("Dependency \(key) has not been registered") + } + guard let typedFactory = factory as? (((Resolver, Parameters) -> Service)?) else { + fatalError("Dependency \(key) did not provide factory closure") + } + let service = typedFactory?(self, parameters) + return service! + } } diff --git a/Tests/SwinjectLightTests/SwinjectLightTests.swift b/Tests/SwinjectLightTests/SwinjectLightTests.swift index ef325b3..25fd0c6 100644 --- a/Tests/SwinjectLightTests/SwinjectLightTests.swift +++ b/Tests/SwinjectLightTests/SwinjectLightTests.swift @@ -2,7 +2,21 @@ import XCTest @testable import SwinjectLight private protocol MockDependency: AnyObject { } +private protocol MockParametersDependency: AnyObject { } private class MockClass: MockDependency { } +private class MockClassWithParameters: MockParametersDependency { + struct Parameters: Equatable { + let foo: String + } + + let parameters: Parameters + let dependency: MockDependency + + init(dependency: MockDependency, parameters: Parameters) { + self.dependency = dependency + self.parameters = parameters + } +} #if canImport(Darwin) @MainActor @@ -29,4 +43,18 @@ final class SwinjectLightTests: XCTestCase { XCTAssertTrue(resolvedDependency is MockClass) XCTAssertTrue(localVariable === resolvedDependency) } + + func testRegisterAndResolveWithParameters() { + let container = Container() + let parameters = MockClassWithParameters.Parameters(foo: "foo") + container.register(MockDependency.self) { _ in MockClass() } + container.register(MockParametersDependency.self, parametersType: MockClassWithParameters.Parameters.self) { resolver, parameters in + MockClassWithParameters(dependency: resolver.resolve(MockDependency.self), parameters: parameters) + } + + let resolvedDependency = container.resolve(MockParametersDependency.self, parameters: parameters) + XCTAssertTrue(resolvedDependency is MockClassWithParameters) + XCTAssertTrue((resolvedDependency as? MockClassWithParameters)?.dependency is MockDependency) + XCTAssertEqual((resolvedDependency as? MockClassWithParameters)?.parameters, parameters) + } } From dc21343e5104583b41ab4c6275238998252d80bc Mon Sep 17 00:00:00 2001 From: Marek Pridal Date: Fri, 28 Nov 2025 15:34:32 +0100 Subject: [PATCH 4/4] Fix swiftlint warning --- .swiftlint.yml | 2 ++ Sources/SwinjectLight/Container.swift | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.swiftlint.yml b/.swiftlint.yml index 62e07e7..12cefdc 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,3 +1,5 @@ excluded: - DIDemoApp - Package.swift + +line_length: 140 \ No newline at end of file diff --git a/Sources/SwinjectLight/Container.swift b/Sources/SwinjectLight/Container.swift index 9d62e42..2a595a9 100644 --- a/Sources/SwinjectLight/Container.swift +++ b/Sources/SwinjectLight/Container.swift @@ -17,7 +17,9 @@ public final class Container { storage[key] = factory } - public func register(_ type: Service.Type, parametersType: Parameters.Type, factory: @escaping (Resolver, Parameters) -> Service) { + public func register(_ type: Service.Type, + parametersType: Parameters.Type, + factory: @escaping (Resolver, Parameters) -> Service) { let key = "\(type)" storage[key] = factory }