0
0
iOS Swiftmobile~5 mins

Dependency injection in iOS Swift

Choose your learning style9 modes available
Introduction

Dependency injection helps your code get the things it needs from outside instead of making them itself. This makes your code easier to change and test.

When you want to swap parts of your app without changing the whole code.
When you want to test your code by giving it fake parts.
When you want to keep your code clean and organized.
When you want to share one object with many parts of your app.
When you want to avoid creating objects inside other objects.
Syntax
iOS Swift
class SomeService {
    func doWork() {
        print("Working...")
    }
}

class Client {
    let service: SomeService

    init(service: SomeService) {
        self.service = service
    }

    func start() {
        service.doWork()
    }
}

The dependency (SomeService) is passed into the client through its initializer.

This is called constructor injection, a common way to do dependency injection.

Examples
Logger is injected into UserManager to handle logging.
iOS Swift
class Logger {
    func log(_ message: String) {
        print("Log: \(message)")
    }
}

class UserManager {
    let logger: Logger

    init(logger: Logger) {
        self.logger = logger
    }

    func createUser(name: String) {
        logger.log("User \(name) created")
    }
}
Using a protocol allows swapping real or mock services easily.
iOS Swift
protocol DataService {
    func fetchData() -> String
}

class RealDataService: DataService {
    func fetchData() -> String {
        return "Real data"
    }
}

class MockDataService: DataService {
    func fetchData() -> String {
        return "Mock data"
    }
}

class DataConsumer {
    let service: DataService

    init(service: DataService) {
        self.service = service
    }

    func printData() {
        print(service.fetchData())
    }
}
Sample App

This example shows how Welcome class gets a Greeter injected. We can change greetings easily by passing different greeters.

iOS Swift
protocol Greeter {
    func greet() -> String
}

class EnglishGreeter: Greeter {
    func greet() -> String {
        return "Hello!"
    }
}

class SpanishGreeter: Greeter {
    func greet() -> String {
        return "¡Hola!"
    }
}

class Welcome {
    let greeter: Greeter

    init(greeter: Greeter) {
        self.greeter = greeter
    }

    func sayHello() {
        print(greeter.greet())
    }
}

let englishWelcome = Welcome(greeter: EnglishGreeter())
englishWelcome.sayHello()

let spanishWelcome = Welcome(greeter: SpanishGreeter())
spanishWelcome.sayHello()
OutputSuccess
Important Notes

Dependency injection makes testing easier by allowing fake objects.

Use protocols or interfaces to make swapping dependencies simple.

Constructor injection is the most common and clear method.

Summary

Dependency injection means giving objects what they need from outside.

This helps keep code flexible, testable, and clean.

Use constructor injection and protocols for best results.