When SwiftUI was announced, one of the early details that caught our attention was the use of static types to optimize parts of the view graph that can’t change:

It’s heavily inspired by the Elm Architecture and React. The biggest unusual (not sure if novel) thing is the use of the type system to optimize out the static subset of the view graph

To see what this means in practice, let’s consider the following example:

let stack = VStack {
    Text("Hello")
    Rectangle()
        .fill(myState ? Color.red : Color.green)
        .frame(width: 100, height: 100)
}

If we ask Xcode for the type of this view, we get a type that contains some View. This is helpful when reading and writing code, but for our purposes we want the real underlying type, without some. We can get the full type by putting the expression above in a variable and then using dump, or by using a mirror:

print(Mirror(reflecting: stack).subjectType)
// output: VStack<TupleView<(Text, ModifiedContent<_ShapeView<Rectangle, Color>, _FrameLayout>)>>

To quickly see what’s going on, we can visualize the type as a diagram:

The type of an expression in Swift is constant: it is computed at compile time. During the lifetime of our SwiftUI program, we can change state variables, observe our model, and render complicated view trees. During each update SwiftUI recomputes the view tree; it then uses the new view tree to update the screen, for instance, inserting or removing views. One thing that doesn’t change is the type of our view tree.

To see why this matters, let’s consider some frameworks similar to SwiftUI.

In our implementation of The Elm Architecture, we do something similar: when the state changes, we re-render our view tree. However, our implementation also includes a diffing step, effectively diffing at tree-level to add and remove views, and update any necessary properties. This approach is common to frameworks like React, languages like Elm, and similar approaches. It can feel wasteful, especially if only a single property has changed.

In SwiftUI, the implementation works differently. In our stack above, SwiftUI knows the type: a vertical stack view with two subviews. During the execution of the program this type will never change — it’s a static property of the code. As such, our program will always render a vertical stack view with a text and a rectangle. When the state changes, some of the views’ properties might change, but the stack view with the two subviews will always persist.

This hard guarantee from the type system means that SwiftUI doesn’t need to do a tree diff. Instead, it only needs to look at the properties of each view, and update those on screen. Theoretically, this still involves walking the entire tree, but walking a tree has a much lower complexity than diffing a tree.

Of course, many applications can’t be written with a fully static view tree: perhaps you want to display items conditionally, or display a list of items (with a variable length), or even display completely different views depending on the state.

Let’s look at these three in detail.

Optional Views

When we want to optionally display a view (based on some state), we can write an if-condition in SwiftUI:

 let stack = VStack {
    if myState {
        Text("Hello")
    }
    Rectangle()
        .fill(myState ? Color.red : Color.green)
        .frame(width: 100, height: 100)
}

The type of stack has now changed:

`VStack<TupleView<(Text?, ModifiedContent<_ShapeView<Rectangle, Color>, _FrameLayout>)>>`