29 November 2016

Dependency Injection in iOS – Not so Scary Syringes


Dependy Injection isn’t brand-new thing in IT world, but it’s just getting more and more popular in iOS at present. So what Dependency Injection really is? It’s design pattern, which implements Inversion of Control paradigm. IoC moves outside component responsible for controlling chosen actions. Its main tasks are expansibility and app division into modules.

Code example without using Dependency Injection could look like that:

It’s simple class, responsible for reading authorization key from NSUserDefaults. Code testing in this form is extremely difficult, because method used for downloading data is responsible for creating NSUserDefaults object, which we can’t control.

There are many ways of injecting dependencies into objects: Extract and Override, Method Injection, Property Injection and Constructor Injection. Method swizzling from Objective-C Runtime can be alternative, but it’s more complicated.

Extract and Override

This method depends on isolating dependencies – in this case NSUserDefaults – and on moving it to another method. Thanks to that, we’ll have possibility to create separate test class, which inherits after UserCredentials and possibility to overwrite returned value.

Method Injection

If dependency is being used by only one method of given class, it’s possible to use Method Injection technique. It depends on communicating object as one of parameters:

In that case, UserDefaults isn’t best example, however Method Injection can be perfect solution in another situations.

Property Injection

As its name indicates, this technique depends on transfering dependencies to object by setting up its property.

After changes, Initialization of UserCredentials object will look like that:

But what will happen, if we don’t set up UserDefault before downloading token? In the current state, app will crash, of course. Problem can be easily eliminated by creating private var, setter and getter

Constructor Injection

Constructor Injection is very similar to Property Injection, but in this case, instead of setting up property after initializing object, NSUserDefaults is being transferred as constructor’s parameter.

Initialization of UserCredentials in that case looks like that:

Thanks to this approach, we can be sure, that credentials.userDefaults won’t change, when app will be working.

Dependency Injection is mostly being mentioned during talking about the subject of TDD, however that pattern has one more important advantage, which isn’t connected to testing at all. Code, which uses injection, can be easily divided into modules thanks to the correct approach. If needed, modules will be pinned in other app locations. This approach is extremely helpful in bigger products, where requirements are often changed.

Michał Karpowicz
Software Developer

iOS developer by day, game developer by night. Swift, Unity, clean code and coffee.