SwiftUI and Jetpack Compose are modern declarative UI frameworks with features that make mobile app development simpler. In declarative frameworks, you describe what the UI should look like in a given state. Any changes in the state will trigger a rebuild of the UI. It's quite a change from imperative UI frameworks such as XML (Android) and UIKit (iOS) but it's quickly gainly popularity and Apple have gone as far as saying SwiftUi is how you should build an app
In this article, you’ll learn about SwiftUI and Jetpack Compose, their similarities and differences, as well as which platforms they support. You’ll gain a better understanding of the learning curve involved for each framework and look at an example of declarative UI while leveraging each of these frameworks.
SwiftUI and Jetpack Compose are basically trying to solve the same challenges, including easier code readability and automatic UI updates on data changes. They have a similar syntax and both rely declarative UI.
A declarative UI allows you to state what the user interface layout on their screen should be without specifying how it will be implemented. Using declarative UI across both platforms means it’s easier for teams to use and implement the same architecture.
With imperative UI frameworks generally, there is a lack of proper state and data updating structure. You need to find specific views where the data has changed and update those individually. This tedious, error prone and becomes harder to debug as the number of views increase.
On the other hand, with a declarative UI, the framework itself updates the necessary views where the data has changed, massively improving state management. Any change in the state will trigger a rebuild of the UI and update its contents. This reduces the amount of boilerplate code written to do the same task. In addition, the logic implementation can be decoupled from the UI, making it easier to track bugs and maintain the code.
The move towards a declarative UI on mobile was actually kickstarted by React Native, trying to bring the best of web development to mobile.
SwiftUI and Jetpack Compose have a similar syntax that is almost indistinguishable. For instance, the following is a simple implementation of a text view and a variable declaration using both frameworks:
Although implementing asynchronous tasks is different in Jetpack Compose and SwiftUI, how they actually behave is quite similar. Similar concepts include having asynchronous tasks that exist only during the lifetime of the composable or the view.
In the code snippet below, an asynchronous task is executed when the composable component is first built and the result is updated when finished. When this composable is destroyed, the asynchronous task is also destroyed:
In the following code snippet, an asynchronous function is executed when the view attached to it is built. The asynchronous function is also destroyed anytime the view is destroyed:
Another similar concept Jetpack Compose and SwiftUI share is the ability to sequentially return multiple values or rather a stream of data from an asynchronous task. With Jetpack Compose, you can achieve this using Flow which comes with different variants such as StateFlow and SharedFlow. On the other hand, SwiftUI achieves this using the @Published property wrapper and the Combine API.
While SwiftUI and Jetpack Compose have similar syntax and declarative UI, they have different distribution methods and are both coupled differently with their respective platforms. Following is a breakdown of the key differences to consider when comparing the two tools.
Many tools and frameworks have huge files and libraries and, therefore, require slightly different distribution methods. SwiftUI and Jetpack Compose have different distribution methods, so including them in your project requires different configurations.
SwiftUI, like all Apple frameworks is bundled in Xcode. After installing the IDE, you can start using the tool immediately. What's nice is that Xcode also includes design tools for building interfaces with SwiftUI using drag-and-drop features. The code is in sync with a screen preview, which means that any change in the code will be immediately reflected in the preview.
In contrast, the Jetpack Compose library can be added to an Android project by including its toolkit dependencies in your app’s build.gradle file to leverage its powerful features, such as composition and UI previews.
For the best developer experience, the latest version of Android Studio is required, which is the go-to IDE for Android application development. You also need to configure the Android Gradle plug-in and Kotlin to the latest version and set the minimum API level to 21 or higher.
Since SwiftUI is already bundled into the IDE, no additional configurations are needed, and it’s easy to start development. Alternatively, with Jetpack Compose, you have to add the dependencies, complete the necessary configurations, and sync them with your project before you can build your application.
Coupling is the level of interdependence between tools, libraries, and their platforms. SwiftUI is tightly dependent on the platform version the application is going to run on. For instance, at Apple’s 2022 Worldwide Developers Conference (WWDC22), a new Swift Charts feature was introduced. Unfortunately, to leverage this new feature, you have to target the most recent platform version, which is iOS 16. Users with older iOS versions are unable to install or update their applications, locking them out. Furthermore, identical code such as removing a List separator line may behave or display differently on iOS 13 vs. 16.
In contrast, Jetpack Compose is not entirely dependent on its platform version as it supports Android SDK 21 and above. When creating a new Android project that targets this SDK or newer, you’ll learn that it covers more than 98 percent of all Android devices produced. With every new innovative feature that Jetpack Compose releases, almost all your users can get the updates and continue using your app:
SwiftUI’s interdependence on the platform version is a limiting factor as it forces you to wait for users to have the latest iOS versions or it only supports users on the latest version, potentially locking out a lot of users.
SwiftUI obviously can only support Apple products but unlike its predecessors, it can be used to build across iOS, macOS, tvOS, and watchOS.
Jetpack Compose is primarily mobile only for Android’s OS, and it doesn’t support any other platform. It is, however, part of a bigger family that includes Compose for Web and Compose for Desktop, which runs on Windows, Linux, and macOS platforms. These tools have been bundled into one artifact, Compose Multiplatform, and this makes it easier to develop Android, desktop, and web user interfaces. Recently, the Android team launched a stable version of Compose that supports Wear OS, thus, broadening its device coverage.
As I mentioned, SwiftUI and Jetpack Compose have similar syntax, architecture, and structure. They are both declarative and are trying to solve the same problems. If you have prior experience with either, it’s relatively easy to learn the other.
SwiftUI has intuitive documentation that details all its essential components, app structure, available user interface elements, and tooling support. In addition, there are detailed video tutorials that show you how to compose simple views, animations, app design, and layouts.
Likewise, Jetpack Compose has detailed documentation with numerous examples for learning purposes. It also has step-by-step tutorials that guide you while developing an application. On top of that, it has an exquisite pathway to help you learn the numerous sample apps that demonstrate how to use the tool’s features.
For beginners, it’s easier to pick up Jetpack Compose because of the numerous resources, tutorials, and sample apps available compared to the more limited resources of SwiftUI. Furthermore, you’re not limited to developing on a macOS system like you are with SwiftUI.
Here's an example of accepting text input from a TextField on SwiftUI. When the button is pressed, the text is added to a list of inputs, which is displayed on the screen. This sample uses the @State property to read and write variables in a view, the @Binding property to access variables in other views, and view modifiers, such as .padding and .font:
Jetpack Compose is built around the Kotlin language, bringing its conciseness and simplicity into play. This example is the same as hte one above - accepting text input from a TextField. This sample uses mutable state variables that trigger UI rebuilds every time their data is updated. It also uses view modifiers to change view properties, such as .padding, .size, and .fonts:
Declarative frameworks are the future of app building and important to learn to stay up to date. Leveraging these frameworks will improve your code readability and help you to easily update the UI with less code.
If you’re interested in making your app even more flexible and letting your entire team push content screens to the app, consider integrating Unflow. Unflow lets anyone on your team create and publish native in-app experiences without any engineering help (think onboarding carousels, engaging stories, quizzes). We've leveraged SwiftUI and Jetpack Compose to build Unflow so feel free to get in touch with any questions you might have about the frameworks too!