Over a month ago, we visited the beautiful city of London. Not to drink some tea, tea and more tea, but to attend iOSCon 2018.

This conference took place over a period of two days and featured some of the regular speakers, like Paul Hudson and Daniel Steinberg, who we had both seen during one of our previous conferences in Paris.

I left the conference with an underwhelmed feeling. It wasn’t that the talks were bad, but I was missing both in-depth and hands-on information in many of the talks, which were kept quite high-level.

One talk which I did find interesting, however, was “Storyboard Revisited” by Paul Stringer, about the Visitor pattern and revisiting storyboards. In this talk, Stringer was trying to make devs consider using storyboards, since they have some advantages, like:

  • less boilerplate code to write,
  • powerful tool for previewing layout and how your app will look,
  • good for cross-functional teams (like working with designers: they can’t read code, but if they see a storyboard it’ll be easier for them to understand).

Storyboards are nice to use, but there are also some drawbacks.

One complaint is the usage of the segues. We are hardcoding strings, for example when doing a performsegue(withIdentifier “someString”) in both the storyboard AND inside your code, which both need to be maintained and in sync.

The ViewController code becomes dependent on the storyboard. So when you want to change the flow of the views inside your app, you’ll need to adjust both code and storyboards because they are highly coupled. When you have a large storyboard it will become very hard to maintain all this coupling. This is one of the reasons why people will start to write their own code for navigating, instead of using the storyboard.

Other code smells for the segues are:

  • Having multiple switch cases in prepare(for segue:) function with identifiers
  • force-casting the destination as a view controller

What do we want?

We want to move all the responsibilities from prepare(forSegue) to somewhere else, so the View shouldn’t deal with it. But how do we do this without all the switch statements and string identifiers?

The goal is that when we make changes in our storyboard, and switch up the flow, that we should not make any changes in our code. This is where the Visitor pattern comes into play. The visitor pattern lets you add operations to the viewcontrollers without changing them. This is done with a technique that is called double-dispatch.

Advantage of the Visitor pattern:

  • all prepare(forSegue) code is being executed without the switch cases
  • doesn’t need an identifier string anymore

How it works

A user has to do a prepare(for segue:) in ViewController A. Instead of writing the code inside that ViewController, it is delegated to the Visitor. This is where the double dispatching takes place. The ConcreteVisitor asks ViewController B if it accepts visitors (first leg of the dispatch). The ViewController B calls back (second part) and says ‘visit me’. It then executes all the code you would normally write in prepareForSegue for that ViewController.   
If you are interested in seeing some of the code behind this mechanism, you can download it from our GitHub.