View Controller Transitions For Big iOS Projects

The View Controller Transitions article provided a way of handling transitions between view controllers that leads to lower coupling and allows for more flexibility when it comes to extending functionality.

One might notice that with the solution described in that article, there is a possibility that we end up with a huge Mediator class, full of else-if clauses.

 
    if ([identifier isEqualToString:@"FromAToB"])
    {
        ...
    }
    else if ([identifier isEqualToString:@"FromBToC"])
    {
        ...
    }
    else if ([identifier isEqualToString:@"FromCToD"])
    {
        ...
    }
    else if ([identifier isEqualToString:@"FromDToE"])
    {
        ...
    }

If we also account for the fact that many of the interactions go both ways, then it’s easy to understand that maintaining the Mediator class can become harder as a project expands and more scenes are added to the codebase.

Conditional statements easily lead to violations of the Open/Closed Principle and a mediator class, monolithic by nature, does exactly that.

So, how can we keep the positive impact of the Mediator Pattern on the interaction of our objects without having to perform Shotgun Surgery on the Mediator class all the time?

Enter the State Design Pattern. According to the Gang Of Four “The State pattern allows an object to change its behavior when its internal state changes.” By combining the Mediator and State patterns we can provide a cleaner way for the Mediator object to handle transitions between view controllers without having to rely on conditionals.

Picking up from the example in View Controller Transitions, we are going to use the State Pattern to delegate the handling of the objects’ interactions to State objects. The Mediator object will keep track of its internal State/Scene, and ask the current State object to deal with the transition.

View Controller Transitions With The State Design Pattern

This way, if we need to change the interaction between two view controllers, we will only need to modify the State/Scene class corresponding to this particular transition and nothing else. Every other participant (the Mediator and the view controllers) won’t have to change.

This design gives developers the freedom to extend their modules and experiment without the fear of breaking things. We can easily add code and features/scenes while keeping the existing codebase intact.

Note: One might argue that this structure adds too much overhead in terms of LOC and should be avoided. While this is a valid argument, we need to keep in mind that design decisions should always reflect the domain in discussion. For example, the design described in this article would be an overkill for a small app that contains only 1-2 scenes, but is helpful  for larger projects.

Also, the State Design Pattern is often target for criticism (Singleton takes the crown of course), especially for having State classes include methods they “don’t need”. There is going to be a series written dedicated to the State Pattern soon and all these issues will be discussed there.

Further Reading

Books:

Agile Principles, Patterns, and Practices in C# (Uncle Bob’s seminal book, a must read)

Head First Design Patterns (In my experience, the best introductory book on Design Patterns)

Design Patterns: Elements of Reusable Object-Oriented Software (The Gang Of Four Book)

UML Distilled (A brief guide to UML that will help with grasping the concepts of Design Patterns)

Articles:

Open Closed Principle (OCP in the world of plugin architectures)

Single Responsibility Principle (The principle defined by the godfather of the term)