Chapter 8: SwiftUI and Jetpack Compose
Kotlin Multiplatform Mobile
link SwiftUI and Jetpack Compose
Introduction
In this section, we will discuss the differences between SwiftUI and Jetpack Compose. Later on, we will provide an overview on how to integrate the KMM repository with our client-side view models.
Let's start with an analysis of Jetpack Compose and SwiftUI.
link Jetpack Compose
Jetpack Compose is Android’s modern toolkit for building native UI. Jetpack Compose uses declarative layouts, instead of the imperative layouts provided by Android's standard libraries. Declarative code is much easier to read and understand, because it expresses what you want to do instead of how you want to do it.
Let's see a quick example of displaying a button on Android:
Declarative UI:
Layout {
Button("click me")
}
Imperative UI:
val button = Button()
button.text = "click me"
val layout = Layout()
layout.add(button)
The declarative approach uses less code, and may even look familiar to those web developers with React experience. React uses the declarative approach to rendering data and has gained popularity in the web development community.
Between Jetpack Compose and SwiftUI, there are many differences in the way we express user interfaces.
link SwiftUI
SwiftUI is an innovative, exceptionally simple way to build user interfaces across all Apple platforms with the power of Swift. SwiftUI also leverages declarative layouts.
Let's see a quick example of displaying a button on iOS:
Declarative UI:
VStack {
Button(
label: { Text("click me") }
)
}
Imperative UI:
let button = UIButton()
button.setTitle("click me", for: .normal)
self.view.addSubview(button)
Once again, the declarative layout is used to describe a view. It feels more intuitive and expresses the view in it's current state. Each time we want to change the View according to it's state we can describe how to reflect the updates automatically.
link Comparing Views
Let's compare how Jetpack Compose and SwiftUI display data.
For example, let's preview the app landing screens and see how both platforms display a row of text:
Android - Composable
@Composable
fun DessertListRowView(dessert: Dessert) {
Row {
Column {
Text(dessert.name, style = MaterialTheme.typography.h6)
Text(dessert.description,
style = MaterialTheme.typography.subtitle2, color = Color.Gray)
}
}
}
iOS - View
struct DessertListRowView: View {
let dessert: Dessert
var body: some View {
HStack {
VStack(alignment: .leading) {
Text(dessert.name)
.font(.title3)
.foregroundColor(.accentColor)
Text(dessert.description_)
.font(.footnote)
.foregroundColor(.gray)
}
}
}
}
As seen in the above code, we have two somewhat similar approaches to building a row of text. The key differences are as follows:
- We declare views in Jetpack Compose as functions, while in SwiftUI we declare them as structs.
Compose functions use the @Composable
annotation, while SwiftUI structs declare a computed property called body
, which implements the View
protocol.
Both approaches implement a tree-like structure to represent the UI. @Composable
functions and View
structs can contain multiple subviews, such as Text
.
- Views can be aligned vertically, horizontally or in a stack. It may be useful to note the syntax for aligning views on each platform:
Compose | SwiftUI |
---|---|
Row | HStack |
Column | VStack |
Stack | ZStack |
Summary
While there are plenty of differences in each platform, both are taking steps toward creating apps with less code. Welcome to the future of mobile app development!
link Architectural Patterns
When writing the client-side code, developers will typically follow one of several common architecture patterns:
- MVC (Model View Controller)
- MVVM (Model View ViewModel)
- MVP (Model View Presenter)
- MVI (Model View Intent)
...and many more!
There is no such thing as "perfect" architecture, and each comes with a set of tradeoffs. With MVVM, we are able to separate the client-side logic from the UI and increase flexibility as any app requirements change.
For an iOS overview of MVVM, visit raywenderlich.com
For an Android overview of MVVM, visit raywenderlich.com
Sharing UI Behavior
Based on the official KMM documentation, if we wanted to share the UI behavior using an architectural pattern, we should use MVP or MVI. These patterns:
Make a clear distinction between the UI and presentation layers.
Are completely decoupled from the UI platform.
Are easily testable without a UI environment.
The problem with sharing UI behavior is that we can only share reactions to inputs and communications with the backend. As the documentation recommends, the user interface (including animations & transitions) should be platform-specific, so we would need write the UI separately anyway.
MVVM
Following the MVVM pattern, we write client-side view models to keep the logic separate from the user interface.
The following graph illustrates how the KMM repository is integrated with the client-side view models.
Once again, we use dependency injection to integrate the repository methods with the client app. In iOS we manually inject each dependency, while on Android we stick with Koin for automated DI.
For more information on architectural patterns for sharing UI behavior, visit kotlinlang.org
link Final Project - Choose Your Platform
Choose your platform. It's time to start building the client-side application for iOS and Android.
Final Project: Create the client-side implementation of the "JustDesserts" mobile app.
- Choose between iOS (SwiftUI) and Android (Jetpack Compose) or both.
- You may also want to follow an architectural pattern, such as MVVM.
For a SwiftUI introduction, visit developer.apple.com
For a Jetpack Compose introduction, visit developer.android.com
App Screens
The following is a complete list of screens to implement:
- DessertListView
- DessertDetailView
- FavoritesListView
- LoginView
- ProfileView
- DessertFormView
- ReviewFormView
For a preview of the completed app screens, download here.
Once again, try to implement this on your own before taking a peak at the solution code.
Solution Code
For the completed code, please refer to the main branch of the Github repository.
Today we introduced the future of mobile app development with SwiftUI and Jetpack Compose frameworks. Then we kick-started the client-side mobile app project.
Congratulations!!
Looking forward to seeing your next mobile app!
Questions? Feedback? Submit a new issue here.