Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

iOS

ABHINAV VERMA
ABHINAV VERMA
6,033 Points

Dependency Injection

I wanted to learn dependency injection but I wanted to know a use case of it in iOS development. Unfortunately the materials online are too verbose and I'm not getting the entire thing. Can anyone explain it in swift 3 and what would the difference between DI and delegation be?

2 Answers

Martin Wildfeuer
PLUS
Martin Wildfeuer
Courses Plus Student 11,071 Points

Hey there! First of all: Dependency Injection and Delegation are separate concepts. It is hard to explain these concepts in short, so I would recommend reading these explanations on Dependency Injection and Delegation first.

Let me give you a quick example of dependency injection: we want to save the users game score so it doesn't get lost once the app is closed. However, we also want to be able to test our game in a separate unit test target. Without DI, we had to test with the persisted data of the app. As the score changes every time we run and play the game, it is hard to predict the initial score. Moreover, any changes in the unit tests would also change the app. Dependency injection to the rescue:

// This is our data store protocol
// Any class that implements it, can set and get game scores
// How and where scores are stored, is up to the class
protocol GameDataStore {
    func getScore() -> Int
    func saveScore(score: Int)
}

// If we want to persist game points to UserDefaults,
// this is the dedicated data store.
// This is the data store we use for our live game data
class UserDefaultsDataStore: GameDataStore {

    private let defaults = UserDefaults.standard

    func getScore() -> Int {
        return defaults.integer(forKey: "score")
    }

    func saveScore(score: Int) {
        defaults.set(score, forKey: "score")
    }
}

// In unit tests, we don't want to overwrite our live game data
// Moreover, we always want to start with a clean slate and not
// with a previously set score
class MockDataStore: GameDataStore {

    private var mockScore = 0

    func getScore() -> Int {
        return mockScore
    }

    func saveScore(score: Int) {
        mockScore = score
    }
}

// This is our game data. It takes care of any game related data
// We focus on how the score is stored: note that at initialization
// we provide a default data store, in our case the UserDefaultsDataStore,
// which will persist scores to user defaults.

struct GameData {

    // This is our data store, the DEPENDENCY
    let dataStore: GameDataStore

    // Here, the dependency is INJECTED at initialization
    init(withDataStore dataStore: GameDataStore = UserDefaultsDataStore()) {
        self.dataStore = dataStore
    }

    var score: Int {
        get { return dataStore.getScore() }
        set { dataStore.saveScore(score: score)}
    }
}

In our live app, we would always instantiate game data like this:

let gameData = GameData()

In out unit tests, we instantiate game data like this:

let gameData = GameData(withDataStore: MockDataStore())

Now you could also write a data store that, instead of saving scores to user defaults, would call an external API to save the scores. You mostly would not want this to happen in unit tests, as these calls can significantly slow down tests. Moreover, you don't want your unit test data be saved to your remote data either.

I know this can be overwhelming at first, but the more you read on it and try to implement it yourself, the clearer these concepts get.

Hope that helps :)

Martin Wildfeuer
Martin Wildfeuer
Courses Plus Student 11,071 Points

Hey ABHINAV VERMA, do you have any questions here? Let me know if I can help you. Moreover, there is now a dedicated course on Dependency Injection here on Treehouse I would like to recommend.

ABHINAV VERMA
ABHINAV VERMA
6,033 Points

Hey Martin, I'm trying to think of use cases to apply it on my own ideas. Till then I think I get the theory.I have viewed the course on dependency injection.