Update: View Controller Data Injection with Storyboards and Segues in Swift

Last week, I wrote about how I do View Controller Data Injection with Storyboards and Segues in Swift

TL;DR – It’s not an ideal solution, but I use Implicitly Unwrapped Optionals (IUOs) that I make sure to use in viewDidLoad (or earlier in the ViewController lifecycle) so there is an explicit 💥 if it’s not set.

Since then, many have chimed in with solution they use, but honestly, they all seem super complicated, ugly, and unreadable. Many mentioned this is why they don’t use storyboards, etc. So I was ok with my not-so-great, but simple, solution.

However, yesterday I read a comment by @cduhn on my I 💖 Storyboards & Nibs blog post that triggered an idea for a slightly better solution.

Here is the comment:

“I look forward to using the implicitly unwrapped var trick when I migrate to Swift. For now, here’s the idiom I like to use for dependency injection with storyboards in Objective C:

1. Each view controller has a public method starting with setDependencies like this:

2. Each view controller has a private method called -assertDependencies, which I call at the top of viewDidLoad.

3. Now simply call setDependencies in prepareForSegue:

One of the things I like about this idiom is that all the dependencies of the class are bundled up in a single method signature, just like a good initializer. If you forget to inject a dependency, you find out about it at compile time.

So here is a more Swifty version of this solution that I’m playing with:

First, create an Injectable Protocol:

Now, my Implicitly Unwrapped Optional dependency can be private:

Now, in prepareForSegue, we can use the inject method:

The thing I really like about this is that it standardizes the inject method for all ViewControllers that need dependency injection. It’s easy to just start typing “inject” in prepareForSegue to see if something needs to be injected vs trying to remember the exact thing that needs to be set!

Enjoy the article? Join over 14,500+ Swift developers and enthusiasts who get my weekly updates.

  • vittoriom

    How do you inject multiple properties of different types into the view controller with this protocol?

    • sergdort

      The power of swift is that you can use tuples as a type
      typealias T = (myViewModel: MyViewModel, service: SomeService)

      • vittoriom

        but then you probably have to inject all properties together

        • membersheep

          I used to inject all my dependences at the same time anyway because I injected them through the init method. This solution is a step forward because it allows me to delegate the initialization to the storyboard. Do you inject your dependencies at separate times?

    • Mox

      If tuples are too straightforward for you, you can also just do a view controller specific struct, with the injected properties inside the struct. You can populate the struct in places you need, and then pass that struct via the inject method.

    • Jeonkwan Chan

      You don’t have to simply use one protocol for all View controller. I’m currently reading the Core Data book from Objc.io, the sample project is using a dedicated ManagedObjectContextSettable protocol. https://github.com/objcio/core-data/blob/master/Moody/Moody/ManagedObjectContextSettable.swift

  • As I understand you use protocol here only to make complier remind you what methods should be implemented, right?

    I would also suggest to assert in willSet property observer and check if property is not nil already (willSet { assert(prop == nil) }) to prevent resetting/changing it’s value at runtime. Not a compile time check but at list something.

  • krishna

    let redPillVC = segue.destinationViewController as? RedPillViewController

    Shouldn’t it be

    let redPillVC = segue.destinationViewController as? Injectable

    Or I’m missing some point?

    • The thing you’re injecting depends on the view controller (it’s a generic type), so you have to be more explicit.

  • Daniel van der Merwe

    Here’s a slightly different version. I refrain from calling it an ‘improvement’ since we can’t mark model as private:

    protocol Injectable {
    associatedtype T
    var model: T! {get set}
    func inject(_: T)
    func assertDependencies()

    extension Injectable {
    func assertDependencies() {
    assert(model != nil)

    • Daniel van der Merwe

      You could even use method swizzling to create a version of viewDidLoad that automatically calls assertDependencies on UIViewControllers than conform to Injectable

      • Augusto Souza

        I liked your solution, I was working in something similar, but instead of attaching a model property to the protocol I tried to introspect into the object to find the property of it that implements T:

        extension Injectable {
        func assertDependencies() {
        let mirror = Mirror(reflecting: self)
        for (_, value) in mirror.children {
        if value is T {
        assert(unwrap(value) != nil)
        private func unwrap(subject: Any) -> Any? {
        var value: Any?
        let mirrored = Mirror(reflecting: subject)
        if mirrored.displayStyle != .Optional {
        value = subject
        } else if let firstChild = mirrored.children.first {
        value = firstChild.value
        return value

        For the method swizzling part of your answer, I think http://nshipster.com/swift-objc-runtime/ might help 🙂

  • Jesse Wolff

    We also add a check to ensure that the IUO isn’t set to nil which would break the “guarantee” we’re trying to setup. Thoughts?

    private var mainText: String! {
    willSet { assert(newValue != nil) }