SwiftUI: Background behind Apple’s next big play

Cross-platform paradigm shift to declarative

A large and fast-moving trend in today’s software industry is to move to a framework that enables and delights developers with declarative user interface code. Traditionally UI code is written using the imperative style of coding which means setting up the UI and mutating it manually when the state changes. To see why we are shifting from the imperative to the declarative coding paradigm on most platforms (Web, iOS/Android), we need to take a step back and see the history of developing UI code across those different platforms and see how they share similar pain points.

Web: UI code

Source: https://skillcrush.com/blog/what-is-jquery-used-for/

From all the way back in 2010 writing user interface code on websites using jQuery was a breeze, but it wasn’t as “straightforward” since you had to maintain UI state yourself and mutate the UI according to state changes. An example of this in JavaScript: clicking an expand button on a truncated paragraph would often look like:

$("#expand").on('click', function (event) {
   if (!this.isExpanded) {
      this.expand(); // A --> B
   } else {
      this.collapse(); // B --> A

It means you need to handle both transitioning from state A → B and back from B → A. If both of these state transformations aren’t symmetrical, it is easy to end up with errors. Wouldn’t it be nice if you could declare what the UI should like based on the isExpanded state variable and the framework would handle the transitions for you when you toggled the boolean value of isExpanded?!

iOS: UI code

Source: https://www.appcoda.com/ios-programming-tutorial-create-a-simple-table-view-app/

The iOS platform was similar… to display a list of items in a UITableView, you were required to declare the data source: an array of items. If you wanted to add an item to the tableView, it required two steps: update the dataSource array (add, remove, delete, or edit an item), and then tell UIKit that the tableView’s dataSource has been updated by reloading the whole table with a tableView.reloadData():

Call this method when you want the table view to completely reload its data.

iOS developers could also opt for more control and only refresh the UI at certain positions (indexes) in the table, to improve performance. Even using the poor performing reloadData method was not foolproof since you could update your dataSource but forget to tell UIKit to update the actual tableView.

A bigger problem was that most developers wanted to support animation and there is a long and complex set of rules on how to tell UIKit the tableView should change depending on how you changed your dataSource. The error output you get shows how easy it is to mess up the invariants when calling UIKit tableView.beingUpdates() and tableView.endUpdates().

Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'

Cross-platform woes

For both platforms: web and iOS we see the problem that the developer has to manage their UI state and implement error-free transitions from different states. We know this is problematic, so is there a better way?

Declarative UI frameworks

Of course! The answer is a paradigm shift to a pattern where a framework manages the UI state. The developer is required to model the UI code in a declarative way: define what the UI looks like given a state. The developer does not need to worry about how to modify the current UI elements to match the state and also when to update the UI on state changes. The framework handles all of that complexity.

SwiftUI @ WWDC 2019

Source: https://developer.apple.com/xcode/swiftui/

To alleviate the pains of managing UI state on iOS, developers were excited (and somewhat apprehensive, will explain below) to see the announcement of SwiftUI at WWDC 2019! Will this solve all of our UI frustrations?! Here is an excerpt from their landing page:

SwiftUI is an innovative, exceptionally simple way to build user interfaces across all Apple platforms with the power of Swift. Build user interfaces for any Apple device using just one set of tools and APIs. With a declarative Swift syntax that’s easy to read and natural to write, SwiftUI works seamlessly with new Xcode design tools to keep your code and design perfectly in sync.

SwiftUI is not the first declarative framework (on iOS or any other platform) but it is one of the largest since it spans across all of Apple’s offerings: macOS, iOS, tvOS, watchOS. SwiftUI solves our problems of UI state management: the framework determines which UI code is tied to which state variables so it can update when the state changes automatically! This means the declarative code is reactive. And it even supports animations!!

When to adopt/learn/explore SwiftUI?

Source: https://www.avanderlee.com/swift/combine/

However, SwiftUI is a large paradigm shift for iOS developers and it will take time getting used to and getting familiar with the ins and outs. Since UIKit was created over the past 13+ years (available since iOS 2.0 which was released in 2008, but development started years before I’d wager), it is understandable that the new UI framework was treated with skepticism as it is hard to recreate the whole UIKit offering, allow bridging between the two frameworks, and provide excellent tooling for the new framework while still supporting both UIKit and SwiftUI.

Overall I’m excited about the future of declarative UI frameworks and specifically SwiftUI and it presents an opportunity for Apple to craft a delightful developer experience and provide immense value by empowering SwiftUI to use all of the latest and greatest iOS UI features (dynamic type, dark mode, localization, and accessibility) with minimal code and sensible defaults.

Iterations of SwiftUI

Source: https://developer.apple.com/news/?id=4ii0mffp

SwiftUI is undergoing its next release as iOS 14 is slated to launch when the new iPhones are released in October(?). It is very promising as they have improved the APIs tremendously since the initial version. I’m looking forward to a future where I can write cross-platform Apple applications with one framework and ensure each platform conforms to high-quality Apple standards with minimal code!

While SwiftUI is awesome to play with, it doesn’t come without its challenges. Stay tuned for my next series on diving deeper into some of the issues I’ve recently faced using SwiftUI while creating an iOS app.