Protocol oriented Flow Controllers

Łukasz Kasperek
Appunite Labs
Published in
3 min readFeb 1, 2016

Recently I’ve been introduced to concept of Flow Controllers by @merowing_ on Twitter. Moment later a blog post on this subject emerged on his blog. I recommend to read it before carrying on with this one.

Are we on the same page? Great ;] I’ve been using an MVVM architecture for a while now. I really like how it helped me to decompose and separate parts of my code. In Flow Controllers I saw an opportunity to move it even further.

As it happend I’ve just had an app to refactor. One with some messy navigation. Great moment to play with this new concept, I thought. The app is written in Swift, so I started obviously with creating a protocol for all flow controllers ;] What should every flow controller have? For sure a navigation controller to be able to push more view controllers.

That’s a start… To continue, let’s imagine a simplified app with UITabBarController with two tabs. One of them is Contacts tab, other is Events tab. From contacts we can go to contact detail view. This view may contain common events subview if there are any for us and given contact. From here we can go further and see this event’s detail view. Similar story with events tab. We can go to event detail and from here to contact detail if any of our contacts is attending this event.

There are two navigation view controllers. One for each tab. We can set root view controller for each of them in flow controllers init methods like so…

Done. We may also want to give some initial state to that view controller, create view model etc. But what is the flowDelegate? Every view controller (at least one that wants to present another view controller(s)) pushed by flow controller will have one and it will be set to self, that is the flow controller. This way the view controller can tell the flow controller to present some new view controller to the user.

Let’s say ContactsListViewController wants to show contact detail view. It has to pass at least a specific contact model then. So the flowDelegate has to have method enabling it to receive this model from view controller. We may declare it in flow delegate protocol, specific to contacts view controller. Let’s name it ContactsListViewControllerFlowDelegate. Declaration will look like this:

To keep compiler happy and our app working we should implement the protocol in our flow controller. Let’s to this with one flow controller’s extension per flow delegate.

At some point we will probably have to extend our flow controller with ContactDetailViewControllerFlowDelegate and so on.

When we finish with contacts tab, we will start with events by creating flow controller for our EventsListViewController. But we will eventually come to EventDetailViewController and it will occur that we have to define another flow delegate protocol with showContactDetail: method and extend another flow controller with its implementation. We can do better than that. So let’s introduce displayable (I’m not sure if it’s a good name, but let’s call it displayables in this blog post).

The idea is every view controller that wants to present i.e. contact detail view controller will be ContactDetailDisplayable. This way ContactsListViewControllerFlowDelegate will no longer have to declare showContactDetail: method. It will be enough if it will be composed of ContactDetailDisplayable.

Then we can provide default implementation for showContactDetail: like so:

We just have to ensure that object using this implementation will be FlowController, so it has a navigationController property. It alse has to implement ContactsDetailViewControllerFlowDelegate’s methods, since the method sets flow delegate to self. But compiler won’t let us forget about these things anyway ;)

Of course flow delegates may be composed of many different displayables and that’s a major cool thing about it. If we have already added a displayable and provided default implementation for its methods, we can now “teach” view controllers to present other view controllers with a single line of code.

Other cool thing is that we have one implementation for configuring and showing given view controller, but we still also have the flexibility to provide another implementation per flow controller or per some specific environment. For example something like this:

All this is just another great possibility enabled by Swift’s protocol extensions and I hope you’ll enjoy this as much as I did when I figured it out :)

We’re going to publish more of mobile related content. Feel free to follow us on Twitter @appunite or me directly @LukaszKasperek

--

--