Dependency Injection with Storyboards

Dependency injection with storyboards is not always straightforward, yet there are a couple techniques that can help you achieve programming nirvana. Dependency injection is a great technique that can help enable more modular and easily testable code. Unfortunately, since Storyboards can often mask how things like transitioning from one view controller to another works under the covers, there aren’t always obvious hooks for implementing dependency injection with Storyboards. Don’t stray to the dark side, singletons are not the answer. There is a way to the light, and I’ll show you a couple techniques for using dependency injection with Storyboards.

What Dependency Injection Is

Have you heard colleagues or friends talk about “dependency injection” but you never really knew what it was? It’s a fancy term for a simple concept. James Shore sums it up really well:

Dependency injection means giving an object its instance variables. Really. That’s it.

Here’s an example view controller definition:

class FirstViewController: UIViewController {
  var persistenceStack: PersistenceStack?
}

FirstViewController defines an instance variable persistenceStack that is open to any other file in the same module. This means that any other class, struct, protocol, whatever, that has access to an instance of FirstViewController may provide it the persistenceStack. Voila, that’s dependency injection. It’s nothing more complicated like that. Said a different way, FirstViewController has a dependency on PersistenceStack and that dependency is provided, or injected, by something else.

Why Dependency Injection Is Important

Dependency injection is an important principle in clean software engineering. The most important reason that you should use dependency injection is that it detaches the implementation of behavior from the interface of behavior. Classes that are open to have their dependencies injected mean that they can be decoupled from the underlying implementation of those dependencies. It’s much easier to purely program to an interface or protocol if you don’t need to know anything about the underlying implementation of the dependency under use.

Imagine you are on a large development team working on a giant iOS application with hundreds of thousands of lines of code. You’re on the “Front-End” team where you focus on the development of the user interface. You spend most of your time in Interface Builder and view controllers. Elsewhere in the company, possibly in a different office, is the “Persistence-Tier” team. The Persistence-Tier team is responsible for writing the mission critical portion of the application that saves things to disk, and keeps those objects in synch with the server-side backend. The thing is, as smart as the Persistence-Tier is, they are constantly changing their mind about the underlying implementation for their piece of the application. Lucky for you, the team has agreed upon a protocol-based dependency injection implementation for access into the persistence layer. As a team member working on view controllers all day, dependency injection prevents you from needing to worry about things like:

  1. How to instantiate the persistence stack.
  2. Whether the persistence stack has been properly configured.
  3. What is the underlying implementation of the persistence stack (eg. CoreData, SQLite, Realm, etc.).
  4. How does using a persistence stack affect automated testing

Instead, you can trust that this dependency will be properly provided to your view controller from some other place, and all you have to do is use it. Remember, it’s just an instance variable that is populated by something else. Your view controller has one less responsibility, and thus is that much closer to achieving the Single Responsibility Principle.

Testability

If you’re reading this blog, you’re probably interested in automated testing. Dependency injection is probably the single easiest way to improve the testability of your iOS code, well any code really, but particularly your UIKit-ladden iOS code. Rather than be tied to the underlying implementation of dependencies, you can provide your own implementation from your test classes, just like you would between classes in the real application. You can now easily stub out things like that persistence layer.

Why Dependency Injection With Storyboards Is Hard

Break out of the role play and back to the real world where most apps are created by a few people on a small team, if not a single person. While the analogy of a giant organization no longer holds true, the need to be able to swap persistent store implementations is something frequently encountered. There’s always a hot new player in the game. Now that you’re bought-in to dependency injection, it’s time to consider how to use the in iOS applications. Storyboards were introduced in iOS 5. Storyboards provide a holistic Interface Builder oriented way to create the user interface for your application. Rather than creating one-off xibs per view controller that then require you the engineer to wire together, a Storyboard allows you to design all your view controllers in one place where you can view all of them at one time, and wire them together such that the relationships between the screens is easily comprehendible in a single glance.

One problem of Storyboards is that they obscure some underlying details of how view controllers actually connect together and communicate. Specifically, when working with a Storyboard-based application, you are rarely writing code in a view controller that manually creates another view controller and brings it onto the screen. Instead, you are relying on segues, and unless you go out of your way to write code to prepare for a segue to happen, or manually trigger a segue, it’s easy to think that the magic of the Storyboard does everything for you.

For example, here’s a Storyboard:

Dependency Injection with Storyboards

This Storyboard represents an application with a navigation controller stack where the root view controller has a button to push a deeper view controller onto the stack. All that behavior provided for free from the Storyboard. Now how in the world would you use dependency injection to provide a dependency to the view controllers in this application? Good question, there are a couple ways.

Dependency Injection with Storyboards

Here are several techniques for implementing dependency injection with Storyboards.

Passing a dependency to an initial view controller

A common pattern you’ll see in iOS applications that use dependency injection is that specific dependencies for the application are instantiated in the custom UIApplicationDelegate for the application. From there, they are then passed into the initial view controller for use throughout the application. Here’s how you can do that. Consider the following Storyboard:

Dependency Injection with Storyboards

A single view controller is designated the Initial View Controller for the application. That means, that view controller will be the first one shown when the application is launched. There’s little corresponding code in the app’s custom UIApplicationDelegate:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

  return true
}

The Storyboard does all the magic for ensuring that view controller is shown on launch. To inject a dependency into that view controller, you need to first create the dependency, and then set it on the view controller. You can use the window and its corresponding rootViewController to get that hook onto the Initial View Controller, like this (assuming a similar implementation of FirstViewController from earlier in this article):

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

  let persistenceStack = PersistenceStack()

  if let firstViewController = window?.rootViewController as? FirstViewController {
    firstViewController.persistenceStack = persistenceStack
  }
  return true
}

Simply use access the rootViewController through the window and then combine that with an if let to downcast it to the specific implementation you need, FirstViewController. Then you have the hook you need and you can inject the dependency.

Passing a dependency to tab bar view controllers

Passing a dependency to view controllers that are part of a tab bar is a little more involved, and the technique is totally inspired from Greg Heo via his awesome two-part raywenderlich.com video tutorial series on Core Data. Storyboards simplify the creation of UITabBar based applications to the point where there is no code representing the creation of the tab bar or its controller. Of course, you can go above and beyond and add code to customize behavior, but you have to know where to do it. Here’s a technique to inject dependencies into view controllers of a tab bar. Imagine an app with this basic Storyboard:

Dependency Injection with Storyboards

It’s nearly the project template for a Tab Based Application. Two view controllers coming off of a UITabBarController. The UITabBarController is designated the Initial View Controller in the Storyboard. In the same project, the AppDelegate has very little code at launch:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
  return true
}

There’s literally nothing happening in that method, the Storyboard is doing everything. Well, lucky for you, application(_:didFinishLaunchingWithOptions:) does actually get called, so it’s the perfect spot to instantiate meaty dependencies and provide them to the initial set of view controllers for the application. But before you modify that code, there’s an important intermediate step to take to ensure everything will be glued together properly, create a protocol! Create a protocol that each view controller will implement that indicates it can have it’s persistence dependency injected. This way, you can write polymorphic in the app delegate to inject the dependency, without needing to know the type of each and every view controller in the tab bar. Create this protocol somewhere:

protocol PersistenceStackClient {
  func setStack(stack: PersistenceStack)
}

Anything conforming to this protocol indicates that it can have a PersistentStack set on it.

Next, update any and all view controllers in the tab bar with an extension that indicates protocol conformance:

extension FirstViewController: PersistenceStackClient {
  func set(stack: PersistenceStack) {
    self.persistenceStack = stack
  }
}

And rinse repeat for each view controller in the tab bar. There are ways to further abstract this so as not to repeat code, but the sample will be simple for now.

Now you can add the magic glue to the app delegate:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

  let persistenceStack = PersistenceStack()

  if let tab = window?.rootViewController as? UITabBarController {
    for child in tab.viewControllers ?? [] {
      if let top = child as? PersistenceStackClient {
        top.set(stack: persistenceStack)
      }
    }
  }
  return true
}

It’s not doing much, but it’s a clever technique. Here’s what’s happening step by step:

  1. Instantiate the dependency.
  2. Grab the rootViewController.
  3. Loop through the child view controllers in the tab bar, and for each that is a PersistentStackClient, set its persistenceStack.

Boom, that’s it, dependency injected into a tab bar controller! See how the protocol allows you to set the PersistentStack in a loop without needing to know the exact type of the view controller?

Passing a dependency from view controller to view controller

Passing a dependency from one view controller to another can be done using:

prepare(for segue: UIStoryboardSegue, sender: AnyObject?)

prepare(for:sender:) is a method defined in UIViewController that may be overridden in your implementations. It’s specifically called right before a segue off of that view controller happens. The provided UIStoryboardSegue has details about specifically which segue was triggered since there could be more than one segue off of a view controller. Included with these details is the destination view controller.

Continuing our earlier example, imagine you have:

class FirstViewController: UIViewController {
  var persistenceStack: PersistenceStack?
}

class SecondViewController: UIViewController {
  var persistenceStack: PersistenceStack?
}

Each view controller has a dependency that may be injected, persistenceStack. Here’s how you may inject persistenceStack from FirstViewController into SecondViewController assuming that they are wired together with a segue in the Storyboard:

class FirstViewController: UIViewController {
  var persistenceStack: PersistenceStack?

  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? SecondViewController {
      destination.persistenceStack = persistenceStack
    }
  }

}

In this implementation of prepare(for:sender:), the destination is retrieved from the UIStoryboarSegue and if it is a SecondViewController then it’s persistenceStack is set, and thus the dependency is injected!

Wrap up

These couple techniques for using dependency injection with Storyboards will bring the cleanliness of your iOS code to the next level. Bart Jacobs’ has a great quote about dependency injection: “It felt as if I graduated as a programmer and no longer needed the singleton pattern to glue the pieces of a project together.” Here’s another good resource titled Nuts and Bolts of Dependency Injection in Swift that you will find helpful, and goes much more in detail on the basics of dependency injection in Swift, and why you should use it. Are you a dependency injection zealot yet? Are you already using dependency injection with Storyboards? How are you using it in your Swift iOS apps? Let everyone know in the comments!

Happy cleaning!

Move Method Refactoring in Swift

In “Refactoring, Improving the Design of Existing Code” by Martin Fowler, he presents the Move Method refactoring.

Here’s a video walkthrough of the Move Method refactoring in Swift and when you might want to use it:

Video Transcript:

Hey, what’s up everybody? It’s Andy from cleanswifter.com back to show you another refactoring from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” Each week I cover a different refactoring from his book showing you how to perform it in Swift 3. This week I’ll show you the refactoring called Move Method. Move Method is finally a refactoring that is the Mac Daddy of all refactorings. Move Method is very similar to ones we’ve seen before, like Extract Method. With Move Method, we’ll see how we can move code from one class to an entirely different class. When I think about refactoring, it’s not so much about changes within a single class. A lot of the refactorings we’ve looked at so far are like that- we’re massaging code within a single class. Right now, with Move Method, it might be the first time so far in this book where we’re going to see how you can take code from one class, and move it to another class all to improve the structure of your existing code. The reason behind Move Method is because one goal of software design is to keep coupling between “things” low. While you want to minimize coupling, you want to maximize cohesion. Cohesion represents how well defined a specific class’s purpose in life is. As soon as one class starts to do more than one thing, it is then not cohesive. For instance, you’ve heard of massive view controllers. Massive view controllers do not have high cohesion. And in fact, they are also probably very tightly coupled to other objects they interact with. Cohesion and coupling go hand in hand. Things that are tightly coupled to other objects often have very low cohesion. Where the opposite is also sometimes true as well. Things that are very cohesive, are also very loosely coupled to other objects. That’s the design you want to strive for, loose coupling and high cohesion. Move Method is a refactoring that is going to let you make changes to two different classes in order to achieve that design goal.

That’s the primary motivation behind Move Method. It’s when you’re going through some code and you see that the code you’re working with, and ultimately will be refactored, is interacting with another class on a detailed level. There might be several lines of code, all bundled together interacting with another class’s instance variables and methods. If you have a method on one class doing a lot of different things on another class, you want to consider moving that method to the other class. A common place I see this in my iOS code, particularly UI code, with UI widgets on screen and what I’m doing to them in view controllers. Let’s get more specific – UILabels. Often times in our code you’re going to come up with a UILabel which has one consistent style across your app. There might be a couple variations depending on where the label is appearing. Rather than repeating code to style your labels, what you can do, and what I’ll show you you can do, is create a subclass of that UILabel and move a method from a view controller that might be styling that label into the UILabel subclass. While I’ll show you this on UILabel, it can apply to a bunch of other UIKit classes like UITextView or UIButton. Anything that appears on screen with a style where you might be writing 5-20 lines of code that would normally be in view controllers – move that to a subclass of the element that you’re styling. Let’s take a look at how to do it in Swift 3.

In this code snippet, there are three different things we’re going to be working with: a struct which represents a name and has two strings for the first and last name. Next is a UIViewController subclass. The third thing is this empty UILabel subclass. To keep this example simple, I could have added some existing behavior into the label, or I could have omitted it and we could have created it during the refactoring. I didn’t do that, so right now it’s empty. Imagine either of those two scenarios, however you want. You’ll see how we’re going to use this with the refactoring. The interesting thing here in this refactoring is this setupNameLabel() method. This is where we are going to apply the Move Method refactoring. The Move Method refactoring at its highest level says we’re going to move this method to a new place. Obviously, the first place I would think to move this to is the NameLabel UILabel subclass. What we can do here is create the new method in the new/destination class, and then, copy and paste the code. This is one of the only times it’s okay to copy and paste code. We can leave the empty shell of the method here for now. We’ll go back and fix that. Now we need to go line by line in NameLabel and fix whatever syntax errors appear. The first one is indicating that firstNameLabel can’t be found. Since we’re now in the nameLabel subclass we don’t need to specify a label, since it is itself that should be modified. Since we’re in Swift, we don’t even need to specify self. The method will set four things: the text color, the alignment, the background color, and its text based on our style for the app. Down here is another interesting thing that we need to change. It’s actually setting the text of the label based on the first name in the Name struct. This is interesting. Unfortunately, NameLabel doesn’t actually know about Name yet. We have a couple options here. How can we get the first name into this method? The first option is actually pass in the Name itself, and this would compile. By doing this, we’re actually creating a coupling between NameLabel and Name – which may or may not be desirable. I’ll just point out another option where we can prevent that coupling is instead- send in the first name directly which we know to be a String. That’s another option. I personally like this option because it’s a little more explicit doesn’t create that coupling between Name and NameLabel. Some would argue that this second option exposes too many details about what NameLabel is actually doing because you need to know to pass the first name in as a String. Ultimately, these are two options you can think through for your specific use case.

Now we have the functionally equivalent setupNameLabel method in the NameLabel subclass. Now we need to go back to our ViewController and make a few changes. First, we’re going to delete the old setupNameLabel method. The compiler will now complain that the method no longer exists. Since we have the nameLabel as a property on the view controller, we can call setupNameLabel on that property. Since setupNameLabel now requires a first name, I will pass it in as a parameter. And there we go, our refactoring Move Method has been applied.

There you have it, that’s the Move Method refactoring. We applied it in a way that we cleaned up our view controller. Anytime you can do that, in my opinion, is a win. It’s so easy as someone new to developing iOS apps, all the way to even senior engineers, to work with code and create code that results with hundreds of lines long view controllers. There have been pattern after pattern created to try to avoid doing that. I think that knowing the basics about refactorings like Move Method help you understand some fundamental ways that you can think about tearing those things apart without needing to commit to a whole new framework or pattern, and instead just write cleaner code. That’s the move method refactoring. Again, the reasons you want to do this are create objects with low coupling and high cohesion. Ultimately you’ll also think about better names for methods and better places for those methods to exist.

I hope you liked this video from cleanswifter.com. This was the Move Method refactoring from Martin Fowler’s book, “Refactoring, Improving the Design of Existing Code.” You can buy the book in the Amazon Affiliate link in the description for this video. Come back next week and I’ll have a new refactoring available.

Thanks, and happy cleaning.

Weekend Reading for August 19, 2016

Weekend Reading for August 19, 2016, click here

Happy Friday fellow Clean Swifters. Who’s watching the Olympics? There’s something that professional software engineering has in common with professional sports: practice makes perfect.

How do you practice your craft?

Reading is a big part of how I stay up to date, and I use the weekends as catch up time. Here’s what I’ll be reading this weekend.

Get “Weekend Reading” delivered in your email, as well as every other cleanswifter.com post, and receive a free screencast on iOS automated testing by signing up here. “Weekend Reading” is created through AWeber’s app, Curate, which I helped create and is entirely written in Swift.

Happy cleaning