diff --git a/Dip/Dip/Definition.swift b/Dip/Dip/Definition.swift index d1206ef..b5352c6 100644 --- a/Dip/Dip/Definition.swift +++ b/Dip/Dip/Definition.swift @@ -81,12 +81,12 @@ public final class DefinitionOf: Definition { var definition = container.register { ServiceImp() as Service } definition.resolveDependencies { container, service in - service.delegate = container.resolve() as Client + service.delegate = try container.resolve() as Client } ``` */ - public func resolveDependencies(block: (DependencyContainer, T) -> ()) -> DefinitionOf { + public func resolveDependencies(block: (DependencyContainer, T) throws -> ()) -> DefinitionOf { guard resolveDependenciesBlock == nil else { fatalError("You can not change resolveDependencies block after it was set.") } @@ -96,7 +96,7 @@ public final class DefinitionOf: Definition { let factory: F var scope: ComponentScope - var resolveDependenciesBlock: ((DependencyContainer, T) -> ())? + var resolveDependenciesBlock: ((DependencyContainer, T) throws -> ())? init(factory: F, scope: ComponentScope) { self.factory = factory diff --git a/Dip/Dip/Dip.swift b/Dip/Dip/Dip.swift index 83eced2..8d79a65 100644 --- a/Dip/Dip/Dip.swift +++ b/Dip/Dip/Dip.swift @@ -97,7 +97,7 @@ public final class DependencyContainer { container.register { ClientImp(service: try! container.resolve() as Service) as Client } ``` */ - public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: ()->T) -> DefinitionOfT> { + public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: () throws -> T) -> DefinitionOfT> { return registerFactory(tag: tag, scope: scope, factory: factory) } @@ -163,7 +163,7 @@ public final class DependencyContainer { */ public func resolve(tag tag: Tag? = nil) throws -> T { - return try resolve(tag: tag) { (factory: ()->T) in factory() } + return try resolve(tag: tag) { (factory: () throws -> T) in try factory() } } /** @@ -186,28 +186,30 @@ public final class DependencyContainer { Though before you do that you should probably review your design and try to reduce the number of dependencies. */ - public func resolve(tag tag: Tag? = nil, builder: F->T) throws -> T { + public func resolve(tag tag: Tag? = nil, builder: F throws -> T) throws -> T { let key = DefinitionKey(protocolType: T.self, factoryType: F.self, associatedTag: tag) let nilTagKey = tag.map { _ in DefinitionKey(protocolType: T.self, factoryType: F.self, associatedTag: nil) } guard let definition = (self.definitions[key] ?? self.definitions[nilTagKey]) as? DefinitionOf else { - throw DipError.DefinitionNotFound(key) + let error = DipError.DefinitionNotFound(key) + print("\(error)") + throw error } let usingKey: DefinitionKey? = definition.scope == .ObjectGraph ? key : nil - return _resolve(tag, key: usingKey, definition: definition, builder: builder) + return try _resolve(tag, key: usingKey, definition: definition, builder: builder) } /// Actually resolve dependency - private func _resolve(tag: Tag? = nil, key: DefinitionKey?, definition: DefinitionOf, builder: F->T) -> T { + private func _resolve(tag: Tag? = nil, key: DefinitionKey?, definition: DefinitionOf, builder: F throws -> T) rethrows -> T { - return resolvedInstances.resolve { + return try resolvedInstances.resolve { if let previouslyResolved: T = resolvedInstances.previouslyResolved(key, definition: definition) { return previouslyResolved } else { - let resolvedInstance = builder(definition.factory) + let resolvedInstance = try builder(definition.factory) //when builder calls factory it will in turn resolve sub-dependencies (if there are any) //when it returns instance that we try to resolve here can be already resolved @@ -218,7 +220,7 @@ public final class DependencyContainer { resolvedInstances.storeResolvedInstance(resolvedInstance, forKey: key) definition.resolvedInstance = resolvedInstance - definition.resolveDependenciesBlock?(self, resolvedInstance) + try definition.resolveDependenciesBlock?(self, resolvedInstance) return resolvedInstance } @@ -246,9 +248,9 @@ public final class DependencyContainer { private var depth: Int = 0 - func resolve(@noescape block: ()->T) -> T { + func resolve(@noescape block: () throws ->T) rethrows -> T { depth++ - let resolved = block() + let resolved = try block() depth-- if depth == 0 { resolvedInstances.removeAll() @@ -307,7 +309,7 @@ public enum DipError: ErrorType, CustomStringConvertible { public var description: String { switch self { case let .DefinitionNotFound(key): - return "No definition registered for \(key). Check the tag, type you try to resolve, number, order and types of runtime arguments passed to `resolve()`." + return "Failed to resolve type \(key.protocolType) - no definition registered for \(key).\nCheck the tag, type you try to resolve, number, order and types of runtime arguments passed to `resolve()` and match them with registered factories for type \(key.protocolType)." } } } diff --git a/Dip/Dip/RuntimeArguments.swift b/Dip/Dip/RuntimeArguments.swift index f1fd2d8..58e957f 100644 --- a/Dip/Dip/RuntimeArguments.swift +++ b/Dip/Dip/RuntimeArguments.swift @@ -41,8 +41,8 @@ extension DependencyContainer { - seealso: `registerFactory(tag:scope:factory:)` */ - public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1) -> T) -> DefinitionOf T> { - return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf T> + public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1) throws -> T) -> DefinitionOf T> { + return registerFactory(tag: tag, scope: scope, factory: factory) } /** @@ -55,63 +55,63 @@ extension DependencyContainer { - seealso: `resolve(tag:builder:)` */ public func resolve(tag tag: Tag? = nil, withArguments arg1: Arg1) throws -> T { - return try resolve(tag: tag) { (factory: (Arg1) -> T) in factory(arg1) } + return try resolve(tag: tag) { (factory: (Arg1) throws -> T) in try factory(arg1) } } // MARK: 2 Runtime Arguments /// - seealso: `register(:factory:scope:)` - public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2) -> T) -> DefinitionOf T> { - return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf T> + public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2) throws -> T) -> DefinitionOf T> { + return registerFactory(tag: tag, scope: scope, factory: factory) } /// - seealso: `resolve(tag:_:)` public func resolve(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2) throws -> T { - return try resolve(tag: tag) { (factory: (Arg1, Arg2) -> T) in factory(arg1, arg2) } + return try resolve(tag: tag) { (factory: (Arg1, Arg2) throws -> T) in try factory(arg1, arg2) } } // MARK: 3 Runtime Arguments - public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3) -> T) -> DefinitionOf T> { - return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf T> + public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3) throws -> T) -> DefinitionOf T> { + return registerFactory(tag: tag, scope: scope, factory: factory) } /// - seealso: `resolve(tag:withArguments:)` public func resolve(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3) throws -> T { - return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3) -> T) in factory(arg1, arg2, arg3) } + return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3) throws -> T) in try factory(arg1, arg2, arg3) } } // MARK: 4 Runtime Arguments - public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4) -> T) -> DefinitionOf T> { - return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf T> + public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4) throws -> T) -> DefinitionOf T> { + return registerFactory(tag: tag, scope: scope, factory: factory) } /// - seealso: `resolve(tag:withArguments:)` public func resolve(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4) throws -> T { - return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4) -> T) in factory(arg1, arg2, arg3, arg4) } + return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4) throws -> T) in try factory(arg1, arg2, arg3, arg4) } } // MARK: 5 Runtime Arguments - public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4, Arg5) -> T) -> DefinitionOf T> { - return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf T> + public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4, Arg5) throws -> T) -> DefinitionOf T> { + return registerFactory(tag: tag, scope: scope, factory: factory) } /// - seealso: `resolve(tag:withArguments:)` public func resolve(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4, _ arg5: Arg5) throws -> T { - return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5) -> T) in factory(arg1, arg2, arg3, arg4, arg5) } + return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5) throws -> T) in try factory(arg1, arg2, arg3, arg4, arg5) } } // MARK: 6 Runtime Arguments - public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> T) -> DefinitionOf T> { - return registerFactory(tag: tag, scope: scope, factory: factory) as DefinitionOf T> + public func register(tag tag: Tag? = nil, _ scope: ComponentScope = .Prototype, factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) throws -> T) -> DefinitionOf T> { + return registerFactory(tag: tag, scope: scope, factory: factory) } /// - seealso: `resolve(tag:withArguments:)` public func resolve(tag tag: Tag? = nil, withArguments arg1: Arg1, _ arg2: Arg2, _ arg3: Arg3, _ arg4: Arg4, _ arg5: Arg5, _ arg6: Arg6) throws -> T { - return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) -> T) in factory(arg1, arg2, arg3, arg4, arg5, arg6) } + return try resolve(tag: tag) { (factory: (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6) throws -> T) in try factory(arg1, arg2, arg3, arg4, arg5, arg6) } } } diff --git a/Dip/DipTests/ComponentScopeTests.swift b/Dip/DipTests/ComponentScopeTests.swift index 486ec9f..674615e 100644 --- a/Dip/DipTests/ComponentScopeTests.swift +++ b/Dip/DipTests/ComponentScopeTests.swift @@ -90,10 +90,10 @@ class ComponentScopeTests: XCTestCase { func testThatItReusesInstanceInObjectGraphScopeDuringResolve() { //given - container.register(.ObjectGraph) { Client(server: try! self.container.resolve()) as Client } + container.register(.ObjectGraph) { Client(server: try self.container.resolve()) as Client } container.register(.ObjectGraph) { Server() as Server }.resolveDependencies { container, server in - server.client = try! container.resolve() as Client + server.client = try container.resolve() as Client } //when @@ -106,9 +106,9 @@ class ComponentScopeTests: XCTestCase { func testThatItDoesNotReuseInstanceInObjectGraphScopeInNextResolve() { //given - container.register(.ObjectGraph) { Client(server: try! self.container.resolve()) as Client } + container.register(.ObjectGraph) { Client(server: try self.container.resolve()) as Client } container.register(.ObjectGraph) { Server() as Server }.resolveDependencies { container, server in - server.client = try! container.resolve() as Client + server.client = try container.resolve() as Client } //when @@ -127,7 +127,7 @@ class ComponentScopeTests: XCTestCase { //given var service2: Service? container.register(.ObjectGraph) { ServiceImp1() as Service }.resolveDependencies { (c, _) in - service2 = try! c.resolve(tag: "service") as Service + service2 = try c.resolve(tag: "service") as Service } container.register(tag: "service", .ObjectGraph) { ServiceImp2() as Service} diff --git a/Dip/DipTests/DipTests.swift b/Dip/DipTests/DipTests.swift index 38c8e14..8bb4303 100644 --- a/Dip/DipTests/DipTests.swift +++ b/Dip/DipTests/DipTests.swift @@ -122,7 +122,7 @@ class DipTests: XCTestCase { XCTFail("Unexpectedly resolved protocol") } catch DipError.DefinitionNotFound(let key) { - typealias F = ()->Service + typealias F = () throws -> Service let expectedKey = DefinitionKey(protocolType: Service.self, factoryType: F.self, associatedTag: nil) XCTAssertEqual(key, expectedKey) } @@ -141,7 +141,7 @@ class DipTests: XCTestCase { XCTFail("Unexpectedly resolved protocol") } catch DipError.DefinitionNotFound(let key) { - typealias F = ()->Service + typealias F = () throws -> Service let expectedKey = DefinitionKey(protocolType: Service.self, factoryType: F.self, associatedTag: "other tag") XCTAssertEqual(key, expectedKey) } @@ -160,7 +160,7 @@ class DipTests: XCTestCase { XCTFail("Unexpectedly resolved protocol") } catch DipError.DefinitionNotFound(let key) { - typealias F = (String)->Service + typealias F = (String) throws -> Service let expectedKey = DefinitionKey(protocolType: Service.self, factoryType: F.self, associatedTag: nil) XCTAssertEqual(key, expectedKey) } diff --git a/DipPlayground.playground/Pages/Circular dependencies.xcplaygroundpage/Contents.swift b/DipPlayground.playground/Pages/Circular dependencies.xcplaygroundpage/Contents.swift index b1934fd..d339aaa 100644 --- a/DipPlayground.playground/Pages/Circular dependencies.xcplaygroundpage/Contents.swift +++ b/DipPlayground.playground/Pages/Circular dependencies.xcplaygroundpage/Contents.swift @@ -44,12 +44,12 @@ Now you can register those classes in container: */ container.register(.ObjectGraph) { - Interactor(networkClient: try! container.resolve()) as NetworkClientDelegate + Interactor(networkClient: try container.resolve()) as NetworkClientDelegate } container.register(.ObjectGraph) { NetworkClientImp() as NetworkClient } .resolveDependencies { (container, client) -> () in - client.delegate = try! container.resolve() as NetworkClientDelegate + client.delegate = try container.resolve() as NetworkClientDelegate } /*: @@ -92,12 +92,12 @@ If we would have used `.Prototype` for one of the components it will lead to the container.reset() container.register(.Prototype) { - Interactor(networkClient: try! container.resolve()) as NetworkClientDelegate + Interactor(networkClient: try container.resolve()) as NetworkClientDelegate } container.register(.ObjectGraph) { NetworkClientImp() as NetworkClient } .resolveDependencies { (container, client) -> () in - client.delegate = try! container.resolve() as NetworkClientDelegate + client.delegate = try container.resolve() as NetworkClientDelegate } let invalidInteractor = try! container.resolve() as NetworkClientDelegate diff --git a/DipPlayground.playground/contents.xcplayground b/DipPlayground.playground/contents.xcplayground index ca67a5f..c8e37c5 100644 --- a/DipPlayground.playground/contents.xcplayground +++ b/DipPlayground.playground/contents.xcplayground @@ -1,5 +1,5 @@ - + diff --git a/README.md b/README.md index 93fe255..dd338a3 100644 --- a/README.md +++ b/README.md @@ -168,12 +168,12 @@ _Dip_ supports circular dependencies. To resolve them use `ObjectGraph` scope an ```swift container.register(.ObjectGraph) { - ClientImp(server: try! container.resolve() as Server) as Client + ClientImp(server: try container.resolve() as Server) as Client } container.register(.ObjectGraph) { ServerImp() as Server } .resolveDependencies { container, server in - server.client = try! container.resolve() as Client + server.client = try container.resolve() as Client } ``` More infromation about circular dependencies you can find in a playground.