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.
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.
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 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.
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.