Navigate back to the homepage

Thinking in SwiftUI

Arvind Ravi
October 14th, 2020 · 2 min read

SwiftUI is starting to mature and it’s time we took a closer look at something that would potentially be the tool of choice for building apps in the next decade.

SwiftUI is vastly different to UIKit or other object oriented UI frameworks. Naturally, this requires developing new intuition to put this framework to good use.

I’m currently reading Thinking in SwiftUI (after which this post is named) and I’m drawing quite a bit of inspiration from the book to document my journey into SwiftUI. I hope you enjoy reading this as much as I have writing it.

In this post we’ll go over some fundamentals of SwiftUI under three different subjects:

  • View Construction
  • View Layout
  • View Updates

View Construction

Let’s take quick look to see how SwiftUI builds views under the hood, feel free to skip this segment if you’re not keen about how views are constructed.

Taking an example of a simple view:

Code:

1@State var counter = 0
2
3var body: some View {
4 VStack {
5 Button(action: { self.counter += 1 }, label: {
6 Text("Tap")
7 })
8 if counter > 0 {
9 Text("You've tapped \(counter) times.")
10 } else {
11 Text("You've not tapped yet.")
12 }
13 }
14}

The body property describes the view that we see on screen, some view is an opaque type that hides the actual type of the body behind it, which in our case would be:

view construction

TupleView, _ConditionalContent are among some of the types that SwiftUI uses internally to wrap other fundamental types to construct a tree of the entire view hierarchy. The if in our case gets wrapped into a type of _ConditionalContent and it’s not really a language construct that gets evaluated during runtime.

This is possible because of new features of swift called Function Builders. Function Builders essentailly allow us to build contents of a function into a single value. View Builder is one of the function builder implementations that SwiftUI leverages to build views, it transforms the contents of the body property into a tree.

This tree is re-rendered every time a State property or an ObservedObject property gets updated.

View Layout

There’s a very obvious difference between the way the layout system works on SwiftUI and UIKit. SwiftUI starts the layout process from the outermost view.

In the above example, that’s the ContentView containing a VStack. The entire available space is given to the ContentView and this trickles down into it’s children. In our case, VStack gets the entire available space, since it’s the only element in the ContentView and VStack divides this further for it’s child elements as necessary.

One thing to note with SwiftUI, is that, we never set a frame on elements. Although, there’s a frame modifier, the way it works isn’t the same as it’s UIKit counterpart.

For example:

1VStack {
2 Text("Hello")
3}.frame(width: 200, height: 200)

In this case, the frame modifier does not set the VStack’s size although it looks like it. The frame modifier wraps the VStack within it in the hierarchy. What goes on under the hood in this case is that, the entire space offered to the ContentView is taken by the frame layout modifier which takes the given parameters and wraps the VStack within it offering it just the speicified dimensions.

In code, this looks something like:

ModifiedContent<VStack<>, _FrameLayout

So, it’s essential to think about layout of elements on SwiftUI from the outside in, rather than inside out.

View Updates

Once the view is constructed and laid out, SwiftUI waits for any state changes to occur to re-render the view tree. There are three different types of properties that can trigger a view change - @State, @ObservableObject and @EnvironmentObject.

Unlike UIKit, the view is not updated in an event handler which eliminates the risk of the application going out of sync with the application’s state. This is fundamentally very different in terms of building apps, but this is what makes SwiftUI quite lightweight and powerful. The view once constructed has a type that’s static which doesn’t change upon state changes - only things that change are things like properties of the views like text of the label or the path of a if statement which is taken.


Working towards understanding the fundamentals is an important first step when it comes to trying to build apps with SwiftUI. I hope this helped as a primer towards this process.

More articles from Swiftla

Building an API Client with Combine

Learn how to build a simple API Client using a URLSession Publisher with Combine.

October 6th, 2020 · 2 min read

State Management in SwiftUI

Apps: What do they all need? Fundamentally, all apps have three types of requirements: Keep track of and mutate state. Respond to user…

May 5th, 2021 · 3 min read
© 2020–2021 Swiftla
Link to $https://twitter.com/arvindravi_Link to $https://github.com/arvindraviLink to $https://www.linkedin.com/in/arvindravizxc/