Dependency Injection in iOS with Swift 5

Tram Ho

Dependency Injection is a broad technique that can be implemented in many different ways. In this article, I will look at Dependency Injection and implement frequently used patterns.

1. Definition of Dependency Injection.

Dependency Injection is a technique that allows a class to depend on an object instead of attending the class to create those objects.

A class will depend on an interface and will implement outside that class. There are 3 things worth noting here:

  • Injector: an instance of dependency and loosen it with a client.
  • Dependency: is an object that requires the client to operate correctly.
  • Client: An object where dependencies are made

Try it out with Swift in the next sections.

2. Client patterns.

There are 4 ways clients can receive dependencies:

  • Initializer
  • Property (property)
  • Interface
  • Ambient context (environment)

2.1 Initializer Injection.

  • Description: Create dependencies through initialization.
  • Usually used when the number of dependencies is small or the object is immutable.
  • Sample code:

  • Advantages:
    • High packing properties
    • Ensure the client is always valid
  • Defect:
    • Dependency cannot be changed later.
    • Becomes bloated with more than 3 dependencies

2.2 Property Injection.

  • Description: Create dependencies via properties.
  • Usually you need to change dependency after initialization. For example Viewcontroller and NSManagedObject
  • Sample code:

  • Advantages:
    • Allow to fix dependency after initialization
    • The code is easier to read
  • Defect:
    • The client will fail if some dependencies are missing
    • Weak packaging
    • Optional attribute must be used

2.3 Interface Injection

  • Description: implemented via setter method or parameter
  • Usually used when multiple clients need to be handled by an injector. Allows injector to perform jobs on the client
  • Sample code

In the example above, Injector handles any client that has HasDependency and DoesSomething protocol. And Injector did doSomething() .

  • Advantages:
    • Lets set the dependency later.
    • Allow injector to apply some client jobs.
    • Injector can handle any client that satisfies the protocol.
  • Defect:
    • The client becomes dependent on itself which complicates flow.

2.4 Ambient Context.

  • Description: The dependency is global through the protocol. This allows substitute implementation if needed.
  • Often used when creating a global access dependency.
  • Sample code:

  • Advantages:
    • Dependency is global and reduces the complexity for clients that use it.
  • Defect:
    • Weak packaging
    • Requires thread safety
    • Heiuer needs to be used with any client that needs manual testing.

3. Dependency Injection Patterns

There are 3 commonly used patterns:

  • Factory
  • Service Locator
  • Dependency injection Container

3.1 Factory

The factory always acts as an injector and connects the client with that dependency. The purpose of the factory is to separate dependencies from the clients.

3.2 Dependency Injection Container

A Container contains several types of abstractions serving a range of functions:

  • Create dependencies with the client
  • Create object
  • Managing the object’s life cycle
  • Apply Container service separately to object

Containers are especially useful when you need to manage multiple clients with multiple dependencies.

3.3 Service Locator.

It is used instead of directly creating dependencies, we need to use the Locator object – responsible for checking each dependency. Locator provides a way to register dependency and manage its life cycle. It does not create dependencies

4. Summary.

Dependency injection is a useful technique, which makes code cleaner and easier to maintain. It allows separate initialization of objects from its use and minimizes connection between components.

Reference: https://www.vadimbulavin.com/dependency-injection-in-swift/
Share the news now

Source : Viblo