Mediator Pattern in Swift

Design Patterns are something we should use not just because they exists, but because they help us to solve a real problem we are trying to fix. The problem I wanted to solve some times ago was the strong coupling of two view controllers when they want to communicate via a segue.

As a very simple example we have an app with an initial view controller (ViewController) and two buttons inside it. When the user presses a button we show another view controller (PhotoViewController) with a photo inside. The photo is different depending on “which” button has been pressed.

The storyboard is something like this:

storyboard

The two segues (“showPanorama” and “showFlowers”) start from the two buttons.

Some implementation details

The ViewController class has a single method prepareForSegue:

PhotoViewController is also very simple and uses an UIImage and an UIImageView to set an image as the background:

Note that the implementation of the class is clearly separated between private and public (that really are internal) members. In Swift we don’t have the objective-C separation between .h and .m files, so we must separate things in a single file.

Also note  that updateBackground is called in the didSet callback of the image property (“change the image and the background will reflect that change”). But in some cases didSet is called when the outlets are not yet set (i.e. in prepareForSegue), in that case we defer the modification of the background to the viewDidLoad method.

So what’s the problem?

The problem of this very common implementation is that the first view controller has to know the implementation of the second view controller. All the problems are in the lines:

This issue is clearer in objective-C were our ViewController class probably begins with the lines:

If, for example, we decide to change the name of the property image in backgroundImage, our ViewController does not compile anymore.

If we want to reuse ViewController class in another app, we must bring together with us the PhotoViewController class!

And imagine this in more complex cases than this very simple app.

Welcome the Mediator

The mediator pattern can be used in these cases to decouple the view controllers. Each view controller is independent and makes no assumptions about the destination controller. These assumptions are delegated to the mediator object.

We also added an enum AppSegues to deal with values instead of literal strings when we use the segue identifiers.

Add the mediator object to the app delegate:

And the prepareForSegue of the first view controller becomes simply:

The  ViewController class has now been decoupled from the PhotoViewController class.

If the app is complex and we have many segues, we can have more than one mediator, each handling the segues of a part of the application. Or the mediator can be decomposed in many objects each relative to a particular segue or group of segues.

Centralize segue identifiers

Another advantage of this strategy is to have all the segue identifiers in the same place for a better check of them. This does not resolve completely the problem of identifiers duplicated in Storyboard and Code but can make life a little better.

The project code of this post can be found at github.

Valerio Ferrucci

Valerio Ferrucci (valfer) develops software on Apple Macintosh since the 1990s until today for MacOS, OSX and, since some years, iOS. He is also a Web (PHP/MySQL/JS/CSS) and Android Developer.

More Posts - Website

Follow Me:
TwitterFacebookLinkedIn

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

One thought on “Mediator Pattern in Swift”

  1. I like the idea of reducing dependencies between view controllers. However, in most apps segue participants are related. It is for example often necessary to configure the destination segue in a way that cannot be statically associated with a segue identifier. For example, the source VC wants to pass on its object context or say a search pattern.

    If a view controller is designed to be (or naturally) reusable, so that you might wish to extract it from an app and copy it to another, it should be isolated from the app (f.e. make it a pod). A client view controller using this module can then well know it’s dependency and resolving the dependency in a different app is then easy (just add it to a Podfile).

    This approach has the huge advantage that you do not split information across the app (having a mediator class knowing of all the implementation details of the whole application) and also does not require that segue names have to be unique across view controller boundaries. It is a bit more effort to manage the pod, but once you get used to, that actually creates a lot more incentives for reuse of modules and components, it’s well wort the effort.

    I don’t think this pattern provides a lot of value when used like this.

Leave a Reply

Your email address will not be published. Required fields are marked *