Better View Controllers with Storyboards using Dependency Injection in Swift

We build professional apps for Android, iOS and mobile web.
Have a look

I want to share a useful pattern that helps keeping view controllers clean, re-usable and encapsulated when using Storyboards.

What's wrong with the way Storyboard uses View Controllers?

Since Apple has introduced Storyboards view controllers are initialized for us.This has created some ugly, ugly coding practices. Often you will see code that sets properties on the destination view controller in prepareForSegue.

With Storyboards the init() method of the view controller is called when a segues is about to be performed. It wont call any custom initializers. This has led to bad practices such as exposing properties so they can be set in the prepareForSegue method.

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "secondSegue" {
            let destination = segue.destinationViewController as! SecondViewController
        // This is the bad part. Person may be an internal property and exposing it will lead to bad coding practice.
            destination.person.firstname = “John”          
            destination.person.lastname = “Appleseed”
        }
    }

A better coding practice is to use a setup methods instead. This will nicely encapsulate the destination view controller.

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "secondSegue" {
            let destination = segue.destinationViewController as! SecondViewController
            destination.setupWithPerson(Person(“John”, lastname: “Appleseed”)
       // VC 2 no longer needs to expose person as a property. Leads to better coding down the track.
        }
    }

I do find this pattern very useful and recommend adding custom setup methods to any view controller. These setups methods will have different signatures to allow the view controller to be configured as needed. It keeps your view controllers encapsulated and you know exactly how they can be setup.

Stop Guessing!

Sometimes code like this is used to setup the destination view controller in prepareForSegue:

            destination.person.firstname = “John”          
            destination.person.lastname = “Appleseed”
            destination.account = someAccount   

In other part os the code this is used to setup the destination VC

            destination.person.firstname = “John”          
            destination.person.lastname = “Appleseed” 

Is that a bug or is that on purpose. You could only guess. And that’s bad.

To avoid guessing what's going on you could have two setup methods.

setupWithPerson(..) setupWithAccount(..)

This is much cleared and less error prone.
Storyboard will give you a fully initialized VC in prepareForSegue(..) and you can now call it’s setup method to prepare it with the data it needs.

Here is tiny sample project on Github.

Dependency Injection?

Dependency Injection (DI) is a pattern that helps with decoupling code. It is used often to make unit testing easier.

We use DI with view controllers to make the view controller externally configureable. This allows us to write much cleaner code, code that is less ambiguous and communicates the intent. Using Dependency Injection you can now make the VC focus on dealing with managing the views and therefore make your VCs much leaner and cleaner.

Check out this diagram that shows how the pattern is used to pass data between two view controllers.

di flow

Storyboards are great and I hope that this pattern will help you to cleanly use configurable view controllers and Storyboards.

Dependency Injection (DI) is a software design pattern. You don't need to dive into DI full swing. But if you like DI then check out Cleanse from Square