Bird
Raised Fist0
iOS Swiftmobile~5 mins

Dependency injection in iOS Swift - Cheat Sheet & Quick Revision

Choose your learning style10 modes available
Recall & Review
beginner
What is dependency injection in simple terms?
Dependency injection means giving an object what it needs instead of letting it create those things itself. It helps keep code clean and easy to change.
Click to reveal answer
beginner
Why is dependency injection useful in iOS Swift apps?
It makes testing easier because you can swap real parts with fake ones. It also helps organize code so parts don’t depend too much on each other.
Click to reveal answer
intermediate
What are the common ways to do dependency injection in Swift?
You can inject dependencies through initializer methods, by setting properties after creating an object, or by using a dependency container that provides needed parts.
Click to reveal answer
beginner
Show a simple Swift example of initializer injection.
```swift
protocol Service {
  func doWork()
}

class RealService: Service {
  func doWork() { print("Working") }
}

class Client {
  let service: Service
  init(service: Service) {
    self.service = service
  }
  func start() {
    service.doWork()
  }
}

let service = RealService()
let client = Client(service: service)
client.start() // prints "Working"
```
Click to reveal answer
intermediate
What problem does dependency injection solve compared to creating dependencies inside a class?
It avoids tight coupling, so classes don’t depend on specific implementations. This makes code easier to change, test, and reuse.
Click to reveal answer
What is the main goal of dependency injection?
ATo make objects create their own dependencies
BTo give objects their dependencies from outside
CTo hide dependencies inside methods
DTo remove all dependencies
Which of these is NOT a common way to inject dependencies in Swift?
AMethod injection
BProperty injection
CInheritance injection
DInitializer injection
Why does dependency injection help with testing?
AIt hides bugs automatically
BIt makes code run faster
CIt removes the need for tests
DIt allows replacing real parts with fake ones easily
In the example: `init(service: Service)`, what is happening?
ADependency is injected via initializer
BDependency is created inside the class
CDependency is ignored
DDependency is deleted
What does tight coupling mean in code?
AClasses depend too much on specific implementations
BClasses are independent and flexible
CClasses have no dependencies
DClasses are loosely connected
Explain dependency injection and why it is helpful in iOS Swift development.
Think about how giving objects what they need from outside helps keep code clean.
You got /3 concepts.
    Describe how you would use initializer injection in a Swift class with a simple example.
    Remember the example with a service protocol and a client class.
    You got /3 concepts.

      Practice

      (1/5)
      1. What is the main purpose of dependency injection in Swift programming?
      easy
      A. To provide objects with their dependencies from outside rather than creating them inside
      B. To make the app run faster by caching data
      C. To automatically generate user interfaces
      D. To encrypt data before saving

      Solution

      1. Step 1: Understand dependency injection concept

        Dependency injection means giving an object the things it needs (dependencies) from outside instead of creating them inside the object.
      2. Step 2: Identify the main purpose

        This approach helps keep code flexible, easier to test, and cleaner by separating concerns.
      3. Final Answer:

        To provide objects with their dependencies from outside rather than creating them inside -> Option A
      4. Quick Check:

        Dependency injection = provide dependencies from outside [OK]
      Hint: Dependency injection means giving dependencies from outside [OK]
      Common Mistakes:
      • Thinking it speeds up app performance
      • Confusing with UI generation
      • Mixing with data encryption
      2. Which of the following is the correct syntax for constructor injection in Swift?
      easy
      A. class Client { func inject(service: Service) { self.service = service } }
      B. class Service { init() { } } class Client { let service: Service; init(service: Service) { self.service = service } }
      C. class Client { var service = Service() }
      D. class Service { func start() {} }

      Solution

      1. Step 1: Identify constructor injection pattern

        Constructor injection means passing dependencies through the initializer (init) of a class.
      2. Step 2: Check which code passes dependency via init

        class Service { init() { } } class Client { let service: Service; init(service: Service) { self.service = service } } shows a Client class receiving a Service instance through its init method and storing it.
      3. Final Answer:

        class Service { init() { } } class Client { let service: Service; init(service: Service) { self.service = service } } -> Option B
      4. Quick Check:

        Constructor injection uses init to pass dependencies [OK]
      Hint: Constructor injection passes dependencies via init method [OK]
      Common Mistakes:
      • Creating dependencies inside the class instead of passing them
      • Using methods instead of init for injection
      • Not storing the injected dependency
      3. Given the code below, what will be printed?
      protocol Logger { func log(_ message: String) }
      class ConsoleLogger: Logger { func log(_ message: String) { print("Console: \(message)") } }
      class Client {
        let logger: Logger
        init(logger: Logger) { self.logger = logger }
        func doWork() { logger.log("Work done") }
      }
      let client = Client(logger: ConsoleLogger())
      client.doWork()
      medium
      A. No output
      B. Work done
      C. Console: Work done
      D. Logger: Work done

      Solution

      1. Step 1: Understand the Logger protocol and ConsoleLogger class

        ConsoleLogger implements Logger and prints messages prefixed with "Console:".
      2. Step 2: Trace the Client usage

        Client is initialized with ConsoleLogger and calls logger.log("Work done"), which prints "Console: Work done".
      3. Final Answer:

        Console: Work done -> Option C
      4. Quick Check:

        Injected ConsoleLogger prints with "Console:" prefix [OK]
      Hint: Injected logger prints message with prefix [OK]
      Common Mistakes:
      • Ignoring the prefix in print statement
      • Assuming no output because of protocol
      • Confusing method names
      4. Identify the error in the following Swift code using dependency injection:
      protocol DataService { func fetchData() -> String }
      class RealDataService: DataService { func fetchData() -> String { "Real Data" } }
      class ViewModel {
        var dataService: DataService
        init() { }
        func load() -> String { dataService.fetchData() }
      }
      medium
      A. dataService is not initialized before use
      B. fetchData() should return Int, not String
      C. ViewModel should not have an init method
      D. RealDataService does not conform to DataService

      Solution

      1. Step 1: Check property initialization

        ViewModel has a non-optional property dataService but its init() does not initialize it.
      2. Step 2: Understand Swift initialization rules

        Non-optional properties must be initialized before use; missing initialization causes a compile error.
      3. Final Answer:

        dataService is not initialized before use -> Option A
      4. Quick Check:

        Non-optional properties must be initialized [OK]
      Hint: Non-optional properties must be set in init [OK]
      Common Mistakes:
      • Assuming default nil for non-optional
      • Confusing return types
      • Ignoring protocol conformance
      5. You want to make a Swift class NetworkManager testable by injecting a protocol NetworkService. Which approach best applies dependency injection and allows easy swapping of real and mock services?
      hard
      A. Create NetworkManager with a fixed real network service inside the class
      B. Make NetworkManager inherit from NetworkService and override methods
      C. Use global variables to hold the network service instance
      D. Define a NetworkService protocol, make NetworkManager accept it via init, and pass either real or mock implementations when creating NetworkManager

      Solution

      1. Step 1: Understand testability with dependency injection

        To test NetworkManager easily, inject a protocol so you can swap real and mock implementations.
      2. Step 2: Identify best practice

        Passing NetworkService via init allows NetworkManager to use any implementation, making testing flexible.
      3. Final Answer:

        Define a NetworkService protocol, make NetworkManager accept it via init, and pass either real or mock implementations when creating NetworkManager -> Option D
      4. Quick Check:

        Inject protocol via init for flexible testing [OK]
      Hint: Inject protocol via init to swap real/mock easily [OK]
      Common Mistakes:
      • Hardcoding real service inside class
      • Using global variables causing tight coupling
      • Misusing inheritance instead of composition
      Recommended

      Ready to prove it?

      Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

      10 questions~5 mineasy hard