Davide Mendolia

Interface Builder Is Dead Long Live SwiftUI

SwiftUI, if you haven't seen it, it's the new kid on the block and the cool kid nonetheless. There is a lot to talk about if you are interested in DSL(Domain-specific language) and what's the right approach to design a GUI DSL, I leave you free to check out other blogs and forums. I will speak here in terms of an iOS developer, basically a user of this framework.

Why I feel comfortable to speak about something that is in Beta compared to other frameworks/toolkits? Because the elements that add value are already here, even if it's not ready yet to replace UIKit, the benefits are already present.

The UIKit Journey

A modern iOS dev journey in learning UIKit starts with playing with .xib files and Storyboard. Even if Interface builder is described as "independently design your interfaces, separate from their implementations" that's generally not the case when you see the amount of code a real app need in the view controller related to the UI. With this first wrong assumption, let's see what the other limitations of Interface Builder are.

If you didn't know it, Storyboard and .xib are XML interface builder files. The XML generated is not documented, hard to read, there are no tools to validate it, and almost impossible to write by hand. That wouldn't be an issue if you didn't have conflict when merging your code with other devs. So what you usually do is stop using Storyboard, or you use them as you would use .nib files. Because being honest segues aren't really practical, we will see with the addition in iOS 13, where you can finally do some dependency injection in a segue.

You can try to convince yourself that these limitations are fine, and that's the best way to figure out the auto layout constraint, and how they relate to the views. But at the same time you want to apply best UI practices, using a design system, and composing your UI with a color palette and font size list and reusable button that you can use through your UI. After a while, you start thinking that this preview mode they convinced you will help you save time was never useful. First of all, because all the demo you saw never had a loading state, apparently, all data are in local at Apple. And there is no way to simulate states in the preview mode or use default data to populate the preview, even if sometimes you try to activate @IBDesignable, you slowly start crying when your XCode is in build loop mode.

At this point, the selling point that was "Simply drag and drop ... onto the design canvas to create a functioning user interface." went out of the window, you already know most of the UIKit elements and can use them by programming them into your ViewController. There is still this auto layout part that you are not comfortable,  but it's neither a win in code or neither in interface builder, so you do mix match code and ib files depending on the projects, mood, team, …

How SwiftUI is solving that, and it’s meant to be the next step for iOS developers?

First of all, it's the syntax, it's code, it could have been XML like Microsoft did more than 10 years ago with XAML. But they choose Swift, it's less verbose, ability to call other Swift code, and under the control of the Apple core team. That will bring more developers to the Swift world, as it's the first Swift only tool that Apple delivers. By being code, you get back one benefit is that you can review it and merge it like other code.

Now the paradigm is a bit different to what you are used to in UIKit. The system will read the definition of your view once and will interpret it and render it using UIKit. Wait, What? What does that mean?

If we look at the following code, it should increment "totalClicked" by tapping the button.

But nothing happened! Why? Did I have done something wrong? Let's debug it. So the code is valid, the debugger is telling me that I increment the variable.

Basically, I have to notify the view that the framework needs to call the body again. Does this mean that the framework will rebuild the UI every time I click the button? Probably not, one thing it's the definition of your UI, and another is how the UIKit interprets and optimize your definition to render the changes.

How to update a Declarative UI?

@State is a wrapper around an Int that every time the value changes it notify the Host(the UIKit interpreter), and the framework will call body again to see if something changes it will interpret the new description and will draw the changes. That's a bit different from what we are used to, instead of having instances of the elements and changing the value, we provide a description and tell the framework when it changed. That includes notifying when you want to toggle a button, change the content of a Textfield, or present an ActionSheet instead by calling a function and changing the state of UI elements in UIKit.

With this in mind, let's see what the other benefits are. There is a live preview initialized by code if you are in macOS Catalina, the good thing is that you can simulate the various state of your App by passing the parameters that you want. So you can preview directly in XCode the multiple states of your App. No need anymore to fake navigation or go through your App, and you can set the views in any state in the preview. Now it's not perfect, it needs to build the App, and in the Beta, it takes time to render or reload the UI, but still less than rebuilding the App and going through the different flows.

No more auto layout!

Another significant change, It's that your layout will be composed mainly of Horizontal Stack, Vertical Stack, and Spacer, no constraint. So we are not using AutoLayout anymore, but if you are Familiar with UIStackView, HStack and VStack are a similar concept. A new addition is Spacer, is what you will use as filler to push your elements apart.

I recommend you to check out "Building Custom Views with SwiftUI" from WWDC2019 at least up to minute 23. It will help you understand how the layout is rendered and what sizes as each view and which position it will have. You will also use ".layoutPriority()" that seems more intuitive than the nightmare that content hugging and content compression resistance priorities are in UIKit.

What are the bad parts of SwiftUI?

View class is clutter with hundreds of methods and modifiers, that gives flexibility on building the framework but really a downside for discoverability. Even with compatibility with UIKit, that means you can use SwiftUI inside UIKit ViewControllers or the other way around, UIViews inside SwiftUI Components. This SDK will only be distributed starting with iOS 13, and it's not backward compatible, so that means, you need to target update or new release of your App, past September 2020 to cover most of the ios 13 users as recommended by Apple. Today, you can't do everything in SwiftUI, it's not really important, it's good enough, the bases are here to stay, and it will give Apple time to mature the API and the tools. Maybe it will never replace UIKit, and we will have to learn how to live with both.

To sum up, I feel that SwiftUI will allow iOS dev to produce better UI by being straightforward to "test" and verify the implementation. Is it ready yet for developers to start to learn? No, the API it's still changing, and it's a good thing, that's what Beta is for. When will it be ready for prime time? If Apple keep is consistency, around XCode 11.2 or 11.3.

In the meanwhile you can check our example App, EndZone in github.