Dependency Injection in Swift

These are a few notes about inversion of control aka dependency injection or simply DI.

“Normal” usage of object is when your object creates additional objects for own usage. In sample below LoginClient creates HTTPService:

class LoginClient {
    let httpService = HTTPService()
}

If we do inversion of that, we will create dependency object (like a service) and pass it into depend (like a client) object.

There is some different types of dependency injections.

Types of Dependency Injections

1. Initializer Injection

class LoginClient {
    let httpService: HTTPService
    init(client: HTTPService) {
        self.httpClient = client
    }
}

let login = LoginClient(client: HTTPService())

2. Property Injection

class LoginClient {
    var httpService: HTTPService?
}

let login = LoginClient()
login.httpService = HTTPService()

3. Method Injection

class LoginClient {
    func login(client: HTTPService) {
        ...
    }
}

let login = LoginClient()
login.login(client: HTTPService())

Now we can inject another object as HTTPService into our LoginClient object. But better to use protocols here:

protocol ConnectionService {
    func login() -> Bool
}

class HTTPService: ConnectionService { }
class OAuthService: ConnectionService { }

class LoginClient {
    var connection: ConnectionService?
    func login() -> Bool {
        return connection?.login()
    }
}

let login = LoginClient()
login.connection = HTTPService()
// or
login.connection = OAuthService()

It’s possible to use any object which confirms to ConnectionService protocol. Using this technique, we can easy mock our connection for LoginClient object. For example:

class SomeTest: XCTestCase {
    class SuccessLogin: ConnectionService {
        func login() -> Bool {
            // Always success, no need to do any network requests
            return true
        }
    }

    func testSignin() {
        let login = LoginClient(client: SuccessLogin())
        let loggedIn = login.login()
        XCTAssertTrue(loggedIn)
    }
}

Links:

https://github.com/Swinject/Swinject


Опубликовано: Апрель 11, 2017 ~ Swift, Protocols