Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c3b601df0f | |||
| 07eb66e87d |
@@ -13,7 +13,7 @@ On the previous page you saw how auto-wiring helps us to get rid of boilerplate
|
||||
Let's say you have following related components:
|
||||
*/
|
||||
|
||||
protocol Service: AnyObject {
|
||||
protocol Service: class {
|
||||
var logger: Logger? { get }
|
||||
var tracker: Tracker? { get }
|
||||
}
|
||||
@@ -101,11 +101,11 @@ serverWithNoClient.optionalClient.value
|
||||
Another example of using auto-injection is circular dependencies. Let's say you have a `Server` and a `ServerClient` both referencing each other.
|
||||
*/
|
||||
|
||||
protocol Server: AnyObject {
|
||||
protocol Server: class {
|
||||
weak var client: ServerClient? { get }
|
||||
}
|
||||
|
||||
protocol ServerClient: AnyObject {
|
||||
protocol ServerClient: class {
|
||||
var server: Server? { get }
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -13,11 +13,11 @@ Very often we encounter situations when we have circular dependencies between co
|
||||
Let's say you have some network client and it's delegate defined like this:
|
||||
*/
|
||||
|
||||
protocol NetworkClientDelegate: AnyObject {
|
||||
protocol NetworkClientDelegate: class {
|
||||
var networkClient: NetworkClient { get }
|
||||
}
|
||||
|
||||
protocol NetworkClient: AnyObject {
|
||||
protocol NetworkClient: class {
|
||||
weak var delegate: NetworkClientDelegate? { get set }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
public protocol Service: AnyObject {}
|
||||
public protocol Service: class {}
|
||||
|
||||
public class ServiceImp1: Service {
|
||||
public init() {}
|
||||
@@ -22,7 +22,7 @@ public class ServiceImp4: Service {
|
||||
|
||||
}
|
||||
|
||||
public protocol Client: AnyObject {
|
||||
public protocol Client: class {
|
||||
var service: Service {get}
|
||||
init(service: Service)
|
||||
}
|
||||
@@ -74,9 +74,9 @@ public class DataProviderImp: DataProvider {
|
||||
public init() {}
|
||||
}
|
||||
|
||||
public protocol ListInteractorOutput: AnyObject {}
|
||||
public protocol ListModuleInterface: AnyObject {}
|
||||
public protocol ListInteractorInput: AnyObject {}
|
||||
public protocol ListInteractorOutput: class {}
|
||||
public protocol ListModuleInterface: class {}
|
||||
public protocol ListInteractorInput: class {}
|
||||
public class ListPresenter: NSObject {
|
||||
public var listInteractor : ListInteractorInput?
|
||||
public var listWireframe : ListWireframe?
|
||||
@@ -96,8 +96,8 @@ public class ListWireframe : NSObject {
|
||||
}
|
||||
}
|
||||
|
||||
public protocol AddModuleDelegate: AnyObject {}
|
||||
public protocol AddModuleInterface: AnyObject {}
|
||||
public protocol AddModuleDelegate: class {}
|
||||
public protocol AddModuleInterface: class {}
|
||||
public class AddWireframe: NSObject {
|
||||
let addPresenter : AddPresenter
|
||||
public init(addPresenter: AddPresenter) {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
///Provides Person entities fetching them with web service
|
||||
///Provides Person entitis fetching them with web service
|
||||
struct SWAPIPersonProvider : PersonProviderAPI {
|
||||
let ws: NetworkLayer
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
protocol FetchableTrait: AnyObject {
|
||||
protocol FetchableTrait: class {
|
||||
associatedtype ObjectType
|
||||
var objects: [ObjectType]? { get set }
|
||||
var batchRequestID: Int { get set }
|
||||
|
||||
@@ -237,7 +237,7 @@ public extension Injected {
|
||||
For that reason if you resolve instance that has a _weak_ auto-injected property this property
|
||||
will be released when `resolve` will complete.
|
||||
|
||||
Use `InjectedWeak<T>` to define one of two circular dependencies if another dependency is defined as `Injected<U>`.
|
||||
Use `InjectedWeak<T>` to define one of two circular dependecies if another dependency is defined as `Injected<U>`.
|
||||
This will prevent a retain cycle between resolved instances.
|
||||
|
||||
- warning: Do not define this property as optional or container will not be able to inject it.
|
||||
@@ -299,7 +299,7 @@ public struct InjectedWeak<T>: _InjectedPropertyBox, AutoInjectedPropertyBox {
|
||||
For that reason if you resolve instance that has a _weak_ auto-injected property this property
|
||||
will be released when `resolve` will complete.
|
||||
|
||||
Use `InjectedWeak<T>` to define one of two circular dependencies if another dependency is defined as `Injected<U>`.
|
||||
Use `InjectedWeak<T>` to define one of two circular dependecies if another dependency is defined as `Injected<U>`.
|
||||
This will prevent a retain cycle between resolved instances.
|
||||
|
||||
- warning: Do not define this property as optional or container will not be able to inject it.
|
||||
|
||||
@@ -61,7 +61,7 @@ public struct DefinitionKey: Hashable, CustomStringConvertible {
|
||||
}
|
||||
|
||||
///Dummy protocol to store definitions for different types in collection
|
||||
public protocol DefinitionType: AnyObject { }
|
||||
public protocol DefinitionType: class { }
|
||||
|
||||
/**
|
||||
`Definition<T, U>` describes how instances of type `T` should be created when this type is resolved by the `DependencyContainer`.
|
||||
@@ -206,7 +206,7 @@ public final class Definition<T, U>: DefinitionType {
|
||||
|
||||
//definitions for types that can be resolved by `forwardsTo` definition
|
||||
//can also be used to resolve self type and it's implementing types
|
||||
//this way container properly reuses previously resolved instances
|
||||
//this way container properly reuses previosly resolved instances
|
||||
//when there are several forwarded definitions
|
||||
//see testThatItReusesInstanceResolvedByTypeForwarding)
|
||||
for definition in forwardsTo.forwardsFrom {
|
||||
@@ -292,7 +292,7 @@ class DefinitionBuilder<T, U> {
|
||||
|
||||
typealias KeyDefinitionPair = (key: DefinitionKey, definition: _Definition)
|
||||
|
||||
/// Definitions are matched if they are registered for the same tag and their factories accept the same number of runtime arguments.
|
||||
/// Definitions are matched if they are registered for the same tag and thier factories accept the same number of runtime arguments.
|
||||
private func ~=(lhs: KeyDefinitionPair, rhs: KeyDefinitionPair) -> Bool {
|
||||
guard lhs.key.type == rhs.key.type else { return false }
|
||||
guard lhs.key.tag == rhs.key.tag else { return false }
|
||||
@@ -300,9 +300,9 @@ private func ~=(lhs: KeyDefinitionPair, rhs: KeyDefinitionPair) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
/// Returns key-definition pairs with definitions able to resolve that type (directly or via type forwarding)
|
||||
/// Returns key-defintion pairs with definitions able to resolve that type (directly or via type forwarding)
|
||||
/// and which tag matches provided key's tag or is nil if strictByTag is false.
|
||||
/// In the end filters definitions by type of runtime arguments.
|
||||
/// In the end filters defintions by type of runtime arguments.
|
||||
func filter(definitions _definitions: [KeyDefinitionPair], byKey key: DefinitionKey, strictByTag: Bool = false, byTypeOfArguments: Bool = false) -> [KeyDefinitionPair] {
|
||||
let definitions = _definitions
|
||||
.filter({ $0.key.type == key.type || $0.definition.doesImplements(type: key.type) })
|
||||
|
||||
+3
-3
@@ -94,7 +94,7 @@ public final class DependencyContainer {
|
||||
Call this method to complete container setup. After container is bootstrapped
|
||||
you can not add or remove definitions. Trying to do so will cause runtime exception.
|
||||
You can completely reset container, after reset you can bootstrap it again.
|
||||
During bootstrap container will instantiate components registered with `EagerSingleton` scope.
|
||||
During bootsrap container will instantiate components registered with `EagerSingleton` scope.
|
||||
|
||||
- throws: `DipError` if failed to instantiate any component
|
||||
*/
|
||||
@@ -298,7 +298,7 @@ extension DependencyContainer {
|
||||
for collaborator in _collaborators {
|
||||
//if container is already in a context resolving this type
|
||||
//it means that it has been already called to resolve this type,
|
||||
//so there is probably a circular reference between containers.
|
||||
//so there is probably a cercular reference between containers.
|
||||
//To break it skip this container
|
||||
if let context = collaborator.context, context.resolvingType == key.type && context.tag == key.tag { continue }
|
||||
|
||||
@@ -453,7 +453,7 @@ extension DependencyContainer: CustomStringConvertible {
|
||||
//MARK: - DependencyTagConvertible
|
||||
|
||||
/// Implement this protocol on your type if you want to use its instances as `DependencyContainer`'s tags.
|
||||
/// `DependencyContainer.Tag`, `String`, `Int` and any `RawRepresentable` with `RawType` of `String` or `Int` by default conform to this protocol.
|
||||
/// `DependencyContainer.Tag`, `String`, `Int` and any `RawRepresentable` with `RawType` of `String` or `Int` by default confrom to this protocol.
|
||||
public protocol DependencyTagConvertible {
|
||||
var dependencyTag: DependencyContainer.Tag { get }
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public enum DipError: Error, CustomStringConvertible {
|
||||
case ambiguousDefinitions(type: Any.Type, definitions: [DefinitionType])
|
||||
|
||||
/**
|
||||
Thrown by `resolve(tag:)` if resolved instance does not implement resolved type (i.e. when type-forwarding).
|
||||
Thrown by `resolve(tag:)` if resolved instance does not implemenet resolved type (i.e. when type-forwarding).
|
||||
|
||||
- parameters:
|
||||
- resolved: Resolved instance
|
||||
|
||||
@@ -81,7 +81,7 @@ extension DependencyContainer {
|
||||
|
||||
- parameters:
|
||||
- tag: The arbitrary tag to use to lookup definition.
|
||||
- builder: Generic closure that accepts generic factory and returns instance created by that factory.
|
||||
- builder: Generic closure that accepts generic factory and returns inctance created by that factory.
|
||||
|
||||
- throws: `DipError.DefinitionNotFound`, `DipError.AutoInjectionFailed`, `DipError.AmbiguousDefinitions`, `DipError.InvalidType`
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ extension DependencyContainer {
|
||||
}
|
||||
```
|
||||
|
||||
Though before you do so you should probably review your design and try to reduce number of dependencies.
|
||||
Though before you do so you should probably review your design and try to reduce number of depnedencies.
|
||||
*/
|
||||
public func register<T, U>(scope: ComponentScope, type: T.Type, tag: DependencyTagConvertible?, factory: @escaping (U) throws -> T, numberOfArguments: Int, autoWiringFactory: @escaping (DependencyContainer, Tag?) throws -> T) -> Definition<T, U> {
|
||||
let definition = DefinitionBuilder<T, U> {
|
||||
@@ -141,7 +141,7 @@ extension DependencyContainer {
|
||||
which factories accept any number of runtime arguments and are tagged with the same tag,
|
||||
passed to `resolve` method, or with no tag. Container will try to use these definitions
|
||||
to resolve a component one by one until one of them succeeds, starting with tagged definitions
|
||||
in order of decreasing their's factories number of arguments. If none of them succeeds it will
|
||||
in order of decreasing their's factories number of arguments. If none of them succeds it will
|
||||
throw an error. If it finds two definitions with the same number of arguments - it will throw
|
||||
an error.
|
||||
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
import XCTest
|
||||
@testable import Dip
|
||||
|
||||
private protocol Server: AnyObject {
|
||||
private protocol Server: class {
|
||||
var client: Client! {get}
|
||||
var anotherClient: Client! {get set}
|
||||
}
|
||||
|
||||
private protocol Client: AnyObject {
|
||||
private protocol Client: class {
|
||||
var server: Server? {get}
|
||||
var anotherServer: Server! {get set}
|
||||
}
|
||||
@@ -488,7 +488,7 @@ class AutoInjectionTests: XCTestCase {
|
||||
XCTAssertNil(server)
|
||||
}
|
||||
|
||||
func testThatItAutoInjectsWhenOverriddenInDefinition() {
|
||||
func testThatItAutoInjectsWhenOverridenInDefinition() {
|
||||
let container = DependencyContainer(autoInjectProperties: false)
|
||||
container.register { ServerImp() as Server }
|
||||
container.register { ClientImp() as Client }
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
import XCTest
|
||||
@testable import Dip
|
||||
|
||||
private protocol Service: AnyObject { }
|
||||
private protocol Service: class { }
|
||||
private class ServiceImp1: Service { }
|
||||
private class ServiceImp2: Service { }
|
||||
private class ServiceImp3 {}
|
||||
|
||||
private protocol AutoWiredClient: AnyObject {
|
||||
private protocol AutoWiredClient: class {
|
||||
var service1: Service! { get set }
|
||||
var service2: Service! { get set }
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
import XCTest
|
||||
@testable import Dip
|
||||
|
||||
private protocol Service: AnyObject {}
|
||||
private protocol Service: class {}
|
||||
private class ServiceImp1: Service {}
|
||||
private class ServiceImp2: Service {}
|
||||
|
||||
@@ -316,7 +316,7 @@ class ComponentScopeTests: XCTestCase {
|
||||
container.register(service, type: Service.self)
|
||||
|
||||
//when
|
||||
//resolve and release right away
|
||||
//resolve and realease reight away
|
||||
_ = try? container.resolve() as ServiceImp1
|
||||
|
||||
//then
|
||||
|
||||
@@ -100,7 +100,7 @@ class DefinitionTests: XCTestCase {
|
||||
XCTAssertFalse(blockCalled)
|
||||
}
|
||||
|
||||
func testThatItRegistersOptionalTypesAsForwardedTypes() {
|
||||
func testThatItRegisteresOptionalTypesAsForwardedTypes() {
|
||||
let def = Definition<Service, ()>(scope: .unique) { ServiceImp() as Service }
|
||||
|
||||
XCTAssertTrue(def.implementingTypes.contains(where: { $0 == Service?.self }))
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
import XCTest
|
||||
@testable import Dip
|
||||
|
||||
private protocol Service: AnyObject { }
|
||||
private protocol Service: class { }
|
||||
private class ServiceImp1: Service { }
|
||||
private class ServiceImp2: Service { }
|
||||
|
||||
private protocol Server: AnyObject {
|
||||
private protocol Server: class {
|
||||
var client: Client! { get }
|
||||
}
|
||||
private protocol Client: AnyObject {
|
||||
private protocol Client: class {
|
||||
var server: Server! { get }
|
||||
}
|
||||
|
||||
|
||||
@@ -164,10 +164,10 @@ class DipUITests: XCTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
protocol SomeService: AnyObject {
|
||||
protocol SomeService: class {
|
||||
var delegate: SomeServiceDelegate? { get set }
|
||||
}
|
||||
protocol SomeServiceDelegate: AnyObject { }
|
||||
protocol SomeServiceDelegate: class { }
|
||||
class SomeServiceImp: SomeService {
|
||||
weak var delegate: SomeServiceDelegate?
|
||||
init(delegate: SomeServiceDelegate) {
|
||||
@@ -176,10 +176,10 @@ class SomeServiceImp: SomeService {
|
||||
init(){}
|
||||
}
|
||||
|
||||
protocol OtherService: AnyObject {
|
||||
protocol OtherService: class {
|
||||
var delegate: OtherServiceDelegate? { get set }
|
||||
}
|
||||
protocol OtherServiceDelegate: AnyObject {}
|
||||
protocol OtherServiceDelegate: class {}
|
||||
class OtherServiceImp: OtherService {
|
||||
weak var delegate: OtherServiceDelegate?
|
||||
init(delegate: OtherServiceDelegate){
|
||||
@@ -189,7 +189,7 @@ class OtherServiceImp: OtherService {
|
||||
}
|
||||
|
||||
|
||||
protocol SomeScreen: AnyObject {
|
||||
protocol SomeScreen: class {
|
||||
var someService: SomeService? { get set }
|
||||
var otherService: OtherService? { get set }
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ class RuntimeArgumentsTests: XCTestCase {
|
||||
|
||||
//Due to incomplete implementation of SE-0054 (bug: https://bugs.swift.org/browse/SR-2143)
|
||||
//registering definition with T? and T! arguments types will produce two different definitions
|
||||
//but when argument of T! will be passed to `resolve` method it will be transformed to T?
|
||||
//but when argement of T! will be passed to `resolve` method it will be transformed to T?
|
||||
//and wrong definition will be used
|
||||
//When fixed using T? and T! should not register two different definitions
|
||||
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
import XCTest
|
||||
@testable import Dip
|
||||
|
||||
private protocol Server: AnyObject {
|
||||
private protocol Server: class {
|
||||
var client: Client! { get set }
|
||||
}
|
||||
|
||||
private protocol Client: AnyObject {
|
||||
private protocol Client: class {
|
||||
var server: Server { get }
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
import XCTest
|
||||
@testable import Dip
|
||||
|
||||
private protocol Service: AnyObject { }
|
||||
private protocol ForwardedType: AnyObject { }
|
||||
private protocol Service: class { }
|
||||
private protocol ForwardedType: class { }
|
||||
#if os(Linux)
|
||||
private class ServiceImp1: Service, ForwardedType { }
|
||||
private class ServiceImp2: Service, ForwardedType { }
|
||||
@@ -136,7 +136,7 @@ class TypeForwardingTests: XCTestCase {
|
||||
resolveDependenciesCalled = true
|
||||
|
||||
//when
|
||||
//resolving via type-forwarding for tag different then tag for original definition
|
||||
//resolving via type-forawrding for tag different then tag for original definition
|
||||
let forwardType = try container.resolve(tag: "tag") as ForwardedType
|
||||
let anyForwardType = try container.resolve(ForwardedType.self, tag: "tag") as! ForwardedType
|
||||
|
||||
|
||||
Reference in New Issue
Block a user