Managing Source Of Truth in SwiftUI

Avanish Rayankula
3 min readFeb 13, 2022

The basic premise of SwiftUI (or any Declarative UI Framework), is that the view is a reflection of a single source of truth.

There are a couple of problems I’ve run into when using SwiftUI in moderately complex UI implementations.

Workflow location is incompatible with source of truth

Let’s say you had an entry point List View, where each List Element was a NavigationLink that takes the user to a separate screen.

What happens if a source of truth update happens to the List which invalidates the existence of the View to which the user navigated to?

The snippet below illustrates this to some extent where ResourceManager (source of truth) removes identifiable elements one by one, based on non-user initiated events. The source of the deletion events in this case is a Timer in this case, but in real world it could be a server sent event about an element’s deletion.

The user starts with 5 elements in the list, but every few seconds the last element is removed. In the worfklow below the user went into the target link for the 4th element (index = 3), but they are automatically popped back to the List View, because the Navigation Link is no longer relevant.

SwiftUI did an amazing job of recongnizing in these cases that the NavigationLink is no longer valid, and it does it’s best to not cause a crash and take the user back into a state that is valid. However, all of this is a bit unexpected for the user, because they have no idea of what just happened.

This is fairly rare in real life situations, but if you are working in areas where multiple users are actively editing the same data, then it might be more common place. Rather than manage the events the way they were handled by SwiftUI automatically, you may want to present a visual indicator to the user to inform them of the change in view state.

One approach is to take some inspiration from how various text editors warn users when the file on disk is different than the contents shown in the editor.

File location changed

How to overcome this challenge? One of the ways I’ve been able to overcome this is by providing a StateManager (think of it as a Presenter in architectures like VIPER), that does receive updates from the source of truth, but also is aware of local state. This Presenter is then responsible for alerting the user so that navigation does not appear as abrupt.

You might be thinking how do I define a Presenter now, but fortunately the amazing developers at Apple have already thought through this one. SwiftUI has the ObservableObject code construct that’s a perfect fit for this (referred to with @ObservedObject in the View)

Managing multiple sources of truth

In complex applications you rarely have views that rely on a single source of truth. Your application may be connecting to multiple servers for different needs. And any of these could update at any point of time.

Having a Presenter once again helps me out in these scenarios because the view State, is provided via a published element by the presenter, but also handles the coordination between various user events and events received from various sources of truth.

The caveat to all of this?

What ends up happening is that the Presenter becomes the source of truth for the view. When the user interactions and sources of truth are manageable, it’s much easier to manage the volume of code in the presenter, but as the interactions become more complex, the coordination amongst the various events is no longer too starightforward.

The presenter then ends up evolving into additional files to manage specific events more easily, however, at least the view code remains extremely straightforward to interpret. This in my opinion is what the essence of SwiftUI is. Make views so easy to write that reviewing the presenter is all a development team really needs to pay close attention to (barring the various iOS version specific nuances that SwiftUI unfortunately suffers from).

--

--

Avanish Rayankula

Software developer, been working on iOS Apps for the last couple of years