Last time on Pragmatic Dependency Injection in Swift, we discussed the horror of global variables and the duplicity of singletons, globals in disguise. Dependency Injection (DI) can help us avoid these pitfalls, but how do we implement DI in Swift without incurring a prohibitive amount of overhead? To find out, we join our regularly scheduled blog post, already in progress…

DI in Swift

So, DI is awesome. Now I want to use this in my Swift project. Let’s consider a standard mobile app. You might have a whole list of objects that had been singletons in the past. Some devs like to call these Manager objects.

  • LocationManager — keeps track of GPS coordinates
  • DataManger — handles data storage
  • ApiManager — coordinates communication to a server
  • LogManager — aggregates debug/error messages to multiple destinations
  • NotificationManager — receives and interprets APNS notifications

And that’s just the tip of the iceberg. In a current project, I’ve got fifteen of these manager style objects. With DI, we need to pass these down through our object hierarchy, but all those init() methods start to look a bit cumbersome with fifteen arguments. Maybe we could just pass what’s needed? That’s a good idea, except the table view cell ten levels deep in the view controller hierarchy suddenly needs access to the LocationManager. You’ll have to create a path to pass it all the way down through the full view controller tree.

So we’ll need to pass everything down, but clearly it’s too cumbersome to do that for each Manager. Also, if you add a new one, you’d need to update a ton of code. We need some kind of Manager holder to encapsulate these into one object that can easily be passed through our application. I like to think of it like a drink caddy that holds multiple bottles of sweet cherry goodness.

Now that we’re moving away from singletons, we’ll change the name from Manager to Controller. Our container object is really a Controller for Controllers, so we’ll call it a MetaController.

Show Me the Code!

Let’s talk about semantics for just a moment. When I say we’re moving away from singletons, I mean the “singleton pattern” of an object that guarantees that it’s only instantiated once and accessed through a static method, like a global variable. In most cases, our Controller objects in the app are single instances, but they are created like normal objects and explicitly passed around via the MetaController. Nothing prevents you from creating more than one of the controller objects, but it’s just not necessary in most cases. If you do need more than one, you have that option.

Back to the MetaController. Here’s what it looks like in basic form.

class MetaController {
    var locationController: LocationController? = nil
    var logController: LogController? = nil
    var apiController: ApiController? = nil 
    var dataController: DataController? = nil 
    var notificationController: NotificationController? = nil 

And that’s it! Okay, it’s just the beginning. Like other components in the system, the controllers themselves often need access to the other controllers in the system. For example, the ApiController needs access to the LogController to log network issues connecting to the server. To make this more convenient, we add a little didSet action in the MetaController to pass the MetaController itself to the payload controllers.

class MetaController {
    var locationController: LocationController? = nil { didSet { passController(locationController) }}
    var logController: LogController? = nil { didSet { passController(logController) }}
    var apiController: ApiController? = nil { didSet { passController(apiController) }}
    var dataController: DataController? = nil { didSet { passController(dataController) }}
    var notificationController: NotificationController? = nil { didSet { passController(remoteNotificationController) }}

    func passController(target: AnyObject?) {
        if var target = target as? MetaControllerConsumer {
            target.metaController = self

Here’s our first glimpse of the MetaControllerConsumer protocol. This swift protocol is adopted by every object in our system that uses the MetaController. The basic definition is super simple and just declares that the consumer will have a place to store the MetaController

protocol MetaControllerConsumer {
    var metaController: MetaController? { get set }

And that’s all that’s necessary, but we want to make this easy to use as well. Every time we access the dataController, it would be a pain to type metaController?.dataController. The great thing about Swift protocols is that you can add default implementations for protocol compliance. This lets us expand the properties required by the protocol, but also define default implementations of synthetic properties to fulfill the protocol requirements. That’s a mouthful. Here’s what that looks like:

protocol MetaControllerConsumer {
    var metaController: MetaController? { get set }
    var locationController: LocationController? { get }
    var logController: LogController? { get }
    var apiController: ApiController? { get }
    var dataController: DataController? { get }
    var notificationController: notificationController? { get }

// default protocol implementation to return the sub controllers from the meta controller
extension MetaControllerConsumer  {
    var locationController: LocationController? {  return metaController?.locationController }
    var apiController: ApiController? { return metaController?.apiController }
    var dataController: DataController? { return metaController?.dataController }
    var userController: UserController? { return metaController?.userController }
    var remoteNotificationController: RemoteNotificationController? { return metaController?.remoteNotificationController }

A MetaControllerConsumer still only has to declare a real property called metaController to hold the container, but can now access the sub-controllers like dataController directly via the default implementation of the computed properties.

We can add more default implementations for other convenience operations too. Logging is a good candidate for these sorts of shortcuts.

extension MetaControllerConsumer {    // Logging shortcuts
    func debugLog(message: String, _ path: StaticString = #file, _ function: StaticString = #function, _ line: UInt = #line){
        logController?.debugLog(message, path, function, line)
    func errorLog(message: String, _ path: StaticString = #file, _ function: StaticString = #function, _ line: UInt = #line){
        logController?.errorLog(message, path, function, line)

With this in place, the logging functions debugLog() and errorLog() are now available in every MetaControllerConsumer. By leveraging Swift protocols like this, it’s easy to add general methods in one place that are accessible everywhere.

BTW, the #file, #function, and #line arguments in these functions are tokens that the compiler recognizes and replaces with the current filename, function name, and line number. Adding a debug statement like debugLog("Bazinga!") can print out

LocationController.swift (line 34): updateLocation(): Bazinga!

which is pretty handy.

Another useful function allows us to quickly pass the MetaController to another object, using the MetaController itself to first check if the target object can consume it.

extension MetaControllerConsumer {
    func passMetaController(target: AnyObject?)         

This is especially useful when programmatically instantiating a new object in the code or configuring a child view controller in prepareForSegue().

We load up the MetaController early in the app bootstrap process (from the app delegate’s didFinishLaunchingWithOptions) and pass it down through our object hierarchy. Initialization is really straightforward.

metaController = MetaController()
metaController?.logController = LogController()
metaController?.locationController = LocationController()
metaController?.apiController = ApiController()
metaController?.dataController = DataController()
metaController?.notificationController = NotificationController()

The MetaController is also handed to the root view controller which handles propagating it down through the view controller ranks.


With the MetaController construct, we reap all the normal DI benefits for testing. For each test, we simply construct a new MetaController, add the controllers that the test needs (replacing with “Fake” subclasses as necessary) and go. This is a little bit of compromise, since we need to know which sub-controllers are required by a class, but it’s a trade-off for the convenience of this proxy model of direct injection. In the strictest sense, we could still provide a fully loaded MetaController if the software under test were truly a black box. In the end, we still have a highly testable framework where we can easily satisfy dependency requirements and create robust, maintainable, explicit test suites.

Solving DI with Swift

Building an app by relying on singletons quickly leads to a mine field of Spooky Action, unintended consequences and unexpected explosions. By moving to a direct injection model, we remove the magic and hidden pitfalls of implicit dependencies and replace them with clear and explicit declarations of dependencies between the components of our app. With the MetaController model and heavy use of Swift protocols, we’re able to encapsulate the overhead of DI in a way that makes it easy and fast to apply DI to our app development process.

At Oak City Labs, we’re always trying to find ways to improve our code’s stability, testability and maintainability. Today we look at the problem of singletons, global state and how to avoid these landmines in the context of Swift.

The Problem

Let’s talk about global variables. Most everyone can agree that global variables are A Very Bad Thing. Globals are undoubtably a code smell and religiously avoided by experienced programmers. Globals are problematic for lots of reasons, but mostly because of Spooky Action At A Distance. If two pieces of code both access a global variable, they can interact via the global variable, often in unexpected and undesirable ways. In this article, Misko Hevery (the Angular guy) dives deep into the many ways this can go pear shaped quickly.

New developers sometimes try to fix global variables by switching to singletons and maintain state within a magic object that is just a static method call away. I’ve heard more than one developer exclaim “Oh no, we never use global variables. We use singletons instead.” The ugly truth though, is that singletons are really just fancier global variables. You still get Spooky Action. You still have implicit and hidden dependencies. Try to write a unit test on a class that relies on a singleton. You can’t look at the exposed interface for this class (think header file) and know about the secret, hidden dependence on that singleton. You must inspect the code and it’s a matter of tedious and confusing mocking of static class methods to try and make this testable. Then write a second test and discover that the tests fail depending on the order in which they run. It’s crazy making!

The most disappointing aspect of singletons is that Apple uses them so often in their own API — UIScreen, NSNotificationCenter, NSUserDefaults, etc. It seems as if they’re encouraging us to use singletons, even when it makes applications fragile and testing difficult.

The Solution — Dependency Injection

“Dependency Injection” (DI) sounds intimidating. And complicated. And scary. People write long, drawn out blog posts about it. But it’s not nearly as intimidating as you might think. At the core, DI just means that you explicitly supply a class with any dependencies, either through initialization or a method call.

Consider this class that uses a two singletons:

class SocialInfo {
    func connectionCount() {
        let twCount = TwitterApi.sharedManager.followerCount
        let fbCount = FaceBookApi.sharedManager.friendCount
        return twCount + fbCount

The connectionCount() function returns the total number of connections on FaceBook and Twitter, using the singleton managers to access those two different APIs. But if we just look at the API, it’s not clear that SocialInfo depends on FaceBookApi and TwitterApi. For all we know, it’s valid to write

let count = SocialInfo().connectionCount()

but looking at the code for that class, we can tell that TwitterApi and FaceBookApi need to be set up and configured first. Imagine if this were a closed source library. We would have no way to know about these implementation details. And we shouldn’t have to care about implementation details anyway.

Now think about what it means to test the SocialInfo class. Our tests shouldn’t rely on network resources, so we’re going to have to mock those singletons. I’ve used several mocking libraries and these are always finicky at best. In Swift especially, the mocking libraries are quite young and this sort of thing is still difficult.

Now let’s consider the same class, rewritten a little for DI.

class SocialInfo {
    let twApi: TwitterApi
    let fbApi: FaceBookApi

    init(twitterApi: TwitterApi, facebookApi: FaceBookApi) {
        twApi = twitterApi
        fbApi = facebookApi

    func connectionCount() {
        let twCount = twApi.followerCount
        let fbCount = fbApi.friendCount
        return twCount + fbCount

With the updates, it’s clear that SocialIinfo depends on a valid instance of TwitterApi and FaceBookApi. Getting a connection count looks like

let count = SocialInfo(twitterApi, facebookApi).connectionCount()

It’s clear that we need to have a configured instance of the Twitter and Facebook API objects ready to pass in so that SocialIinfo can use them to connect with the services.

And testing is much easier too! Instead of having to build mock objects when can create FakeTwitterApi and FakeFaceBookApi objects that are subclasses of our real objects and just hardwired to return known values for the counts. This is really straightforward, readable, and doesn’t require any mocking.

So that’s dependency injection — simply the idea that dependencies are passed in explicitly rather than pulled out of the ether via some magical singleton or (gasp!) global variable.

Tune in next time for the exciting conclusion and the implementation of pragmatic dependency injection in Swift.