SwiftUI – 3 insights from practical usage

NOVEMBER 24, 2019

There’s a lot of info about SwiftUI out already, and the community seems very excited to start using it. Since there are so many resources and tutorials out already I thought I’d share some of the most interesting things I’ve come across in practical usage.

#1 – It’s not production ready just yet

Don’t get me wrong I’m all for it. In the apps I’ve been making with SwiftUI I’ve been having a blast, it’s most definitely the future of creating UI for Apple devices. I think they combined the best of the programmatic world of UI and the Interface Builder world of UI. I don’t believe it is production ready for a few reasons. Mostly around navigation and a UI elements that just don’t exist yet. 

Navigation Issues: When making a fairly simple app I created a NavigationBarItem with a NavigationItem inside, that represents an ‘add’ button on the right side of the navigation bar. Tapping the button pushes a detail view onto the nav stack. The detail screen allows a user to create new content that will show up in a list on the previous screen. For some reason tapping the back button on the detail view would not trigger the previous screen to re-render it’s content. So it would appear that the detail screen was not actually creating new content. As of Xcode 11.2.1 a simple push-pop actually crashes the app so there it’s not just my imagination that something is off with it. Apparently Apple knows about it too. However, using a  workaround I can get the push-pop working without crashing. To me this is a deal breaker, if there needs to be workarounds for simple navigation it can’t be trusted for production use. For side projects or small apps in the App Store you can probably get away with it, but for any apps with serious money on the line it just isn’t ready yet. 

UI Elements Missing: As of Xcode 11.2.1 there are several first party SwiftUI UI elements. For example: List, HStack, VStack, Color, Spacer, Text, TextField. These are great for making some really cool UI, but one thing I noticed missing was editable TextViews. The Text element is basically the equivalent of a UILabel. You can display text easily but the user cannot edit the text. The TextField label is the equivalent to a UITextField, which does allow users to enter text but is only meant to be one line of text. So far there is no equivalent to the UITextView, some answers on stackoverflow point to wrapping UITextView as a SwiftUI element which certainly works but does feel a little glitchy at times. I imagine there will be a TextView or existing elements will be modified to allow UITextView like behavior but at the moment it just doesn’t exist.

Like the Swift language itself has changed over the years, I imagine SwiftUI will go through its own changes and growing pains before it’s in a stable form. If you are able to use it in your apps in a safe way / don’t care about possible bugs then I would say go for it, it’s definitely what will be used in the future, but know there are risks. 

#2 – Order of operations make a big difference

In math this makes sense, but in code it seems a little weird. At first I really did not like the idea that the order in which you style an element can vary drastically. This means that programmers need to now be mindful of how they do simple styling operations, which creates new ‘tribal knowledge’ that can be confusing to new-comers. However, after playing around with this more I’ve found it to be incredibly flexible and powerful. Instead of having to completely redo the structure of a component, simply rearranging it’s styling can drastically change how it looks. This makes real world re-usability possible. I instantly thought of how hard it is to make UITableView cells reusable without a lot of leg work. 


Same element with different styling
// Example A
SomeReusableView(
    title: "TITLE ONE",
    subtitle: "subtitle",
    onEditTap: {
        print("did tap edit")
    }
)
.padding(10)
.frame(maxWidth: 340)
.background(Color.regularOrange)
.cornerRadius(10)
.accentColor(Color.lightOrange)
// Example B
SomeReusableView(
    title: "TITLE TWO",
    subtitle: "subtitle",
    onEditTap: {
        print("did tap edit")
    }
)
.padding(EdgeInsets(top: 15, leading: 20, bottom: 15, trailing: 20))
.frame(maxWidth: 400)
.background(Color.regularOrange)
.accentColor(Color(.lightGray))
.overlay(
    UnavailableView()
    .background(Color(.black).opacity(0.35))
)
.cornerRadius(10)

The overlay modifier is really nice.

// Example C
SomeReusableView(
    title: "TITLE THREE",
    subtitle: "subtitle",
    onEditTap: {
        print("did tap edit")
    }
)
.padding(EdgeInsets(top: 10, leading: 10, bottom: 10, trailing: 10))
.background(Color(.orange))
.cornerRadius(10)
.padding(EdgeInsets(top: 20, leading: 20, bottom: 20, trailing: 20))
.background(Color(.lightGray))
.frame(maxWidth: 400)
.accentColor(Color.lightOrange)
.cornerRadius(10)

This last example is really interesting to me. By using the padding, background, and cornerRadius modifiers on the same element multiple times it creates a view that appears nested in another view.

Using element modifiers it’s really easy to get vastly different looking UI without ever modifying the actual code of the underlying element.

#3 – The Canvas feature is amazing 

I was really excited for the new Canvas feature in Xcode, although I wasn’t sure if it was more of a gimmick than actually useful. However, so far it’s proven that it’s going to be paramount to creating UI moving forward.

Over the years I’ve flip flopped over whether or not Interface Builder should be used. Early on I only did everything programmatically until I had a manager that made me use IB. I wasn’t thrilled about it but as more and more devices started being added to the iOS eco system, it was getting harder and harder to support everything programmatically. In order to see how the UI looked I would have to run it on every device in order to see what it looked like. Alternatively when using IB I could easily see how it looked without running the app and change the device to see how it reacts to different sizes. That was my manager’s argument that it made it easy for anyone on the team to see what the screen looks like and not have to dig through a ton of code. Now IB comes with its own problems. it can cause merge conflict headaches, and feel like ‘magic’ where a lot of developers don’t trust it and don’t really understand it. There are pros and cons to any approach.

This is where the Canvas really shines. It allows you to control everything programmatically but also instantly render it without having to run the app.

Not so reactive UI on multiple devices

It combines the best of the programmatic and IB worlds. This has been incredibly helpful when messing around with SwiftUI, being able to modify a line of code and see how it affects the rendered view. The other great thing is that you can preview multiple devices all at the same time. So you can quickly see how your changes affect multiple screen sizes.

TLDR

SwiftUI is really promising but it has some quirks and bugs that make it risky to use in production code at this time (Xcode 11.2.1).