Data in SwiftUI, Part 2: Views as a function of data
Table of Contents
Part 2 in a series on understanding data in SwiftUI. We will talk about the key that makes principles in part 1 possible in SwiftUI. And how this resulting in a reduction of the complexity of UI development.
- Data flow in SwiftUI, Part 1: Data
- Data flow in SwiftUI, Part 2: Views as a function of data
- Data flow in SwiftUI, Part 3: Tools
We know from part 1 that data is the main focus for SwiftUI, but without cooperation from a view and framework, it might not be a pleasant experience implementing it.
Views as a function of state
Even though you set the data right, you have a single source of truth, and you set dependency correctly. Doing this in UIKit might still result in a big chunk of code. That's because, by nature, UIKit is an event-driven user interface; it needs someone to coordinate all of these events and glue them together. That is why we need UIViewController
in UIKit.
Here is an example from WWDC 2019 session[1]. It is a music player app with a PlayerView
as a parent view, which contains PlayerButton
showing play/pause image based on isPlaying
state.
The above diagram should familiar to you, PlayerViewController
holds a reference of PlayerView
and PlayButton
. It keeps a single source of truth (isPlaying
) in sync between PlayerView
and PlayButton
. PlayButton
holds a reference of isPlaying
, change the image (play/pause) based on this state and fire an action when got tapped. PlayerViewController
listens to button action and changes the state accordingly. Once playing state change, it changes the color of the song title in PlayView
.
// An example of some implementation of PlayerViewController
var isPlaying: Bool = false {
didSet {
// change song label color
}
}
func viewDidLoad() {
configureView()
loadData()
}
private func configureView() {
// setup song label color
// setup playButton state based on isPlaying
}
@objc func playButtonDidTap(sender: Any) {
// toggle isPlaying
// configure playButton
}
As you can see, the fact that UIKit communicates using events makes it difficult to know what the resulting view would be at a given time. And there are so many places that can go wrong.
Views are a function of state, not of a sequence of events.
– WWDC 2019, session 226[1:1]
If UIKit said to be an event-driven user interface, SwiftUI would be data-driven. The above quote from WWDC 2019 session[1:2] sums the situation of UIKit and SwiftUI nicely.
View in UIKIt usually a result of sequences of events, whether target-action, delegate, or notification. View in SwiftUI, on the other hand, designed to depend solely on data.
Let see some example.
struct PlayerView: View {
let episode: Episode
@State private var isPlaying: Bool = false
var body: some View {
VStack {
Text(episode.title).foregroundColor(isPlaying ? .white: .gray)
Text(episode.showTitle).font(.caption).foregroundColor(.gray)
PlayButton(isPlaying: $isPlaying)
}
}
}
struct PlayButton: View {
@Binding var isPlaying: Bool
var body: some View {
Button(action: {
self.isPlaying.toggle()
}) {
Image(systemName: isPlaying ? "pause.circle": "play.circle")
}
}
}
You might not understand some of the syntaxes, but we can all agree that a SwiftUI view is quite easy to understand. We can declare views in the form of function that takes data as an arugment. PlayerView
's episode title color change according to isPlaying
. PlayButton
image showing play/pause based on isPlaying
. We know exactly how it looks based on a given data, isPlaying
.
Following is the same view interaction diagram, but this time for SwiftUI.
You can easily support sarunw.com by checking out this sponsor.
Offline Transcription: Fast, privacy-focus way to transcribe audio, video, and podcast files. No data leaves your Mac.
Declarative UI
SwiftUI said to be declarative UI. It has a way to declare all principles we learn in this declarative world. We can declare data as a source of truth or dependency, and view as a function of those data. SwiftUI will do take care of the rest for us.
The declarative UI make SwiftUI shine, the framework handle everything that we have to do it manually in UIKit. It makes the concept of view controller not relevant anymore in SwiftUI.
The purpose of the view controller is to manage views and their interaction. Most of the codes in view controller are for responding to user interaction from its views. Setting up target-action to a button, listen for a delegate. Observe to model change and response to that by reload your table view or change some labels. You have to do all of this manually, which is error-prone, and the complexity grows as your app grows.
SwiftUI does all the heavy lifting, which allows us to focus on things that matter, manage the data of your app by defining the right source of truth and its dependency.
The whole purpose of view controller is to keep your data in sync with your view
The fact that we don't have to manage data ourselves makes the complexity in UI development significantly reduce.
What's next
In the following article, we will go through all the tools available, including the one shown in the example @State
and @Binding
.
Related Resources
Data flow in SwiftUI, Part 1: Data
Data flow in SwiftUI, Part 3: Tools
Data Flow Through SwiftUI
You can easily support sarunw.com by checking out this sponsor.
Offline Transcription: Fast, privacy-focus way to transcribe audio, video, and podcast files. No data leaves your Mac.
References
WWDC 2019 session 226, Data Flow Through SwiftUI https://developer.apple.com/videos/play/wwdc2019/226/ ↩︎ ↩︎ ↩︎
Read more article about SwiftUI, iOS, Data, Property Wrapper, or see all available topic
Enjoy the read?
If you enjoy this article, you can subscribe to the weekly newsletter.
Every Friday, you'll get a quick recap of all articles and tips posted on this site. No strings attached. Unsubscribe anytime.
Feel free to follow me on Twitter and ask your questions related to this post. Thanks for reading and see you next time.
If you enjoy my writing, please check out my Patreon https://www.patreon.com/sarunw and become my supporter. Sharing the article is also greatly appreciated.
Become a patron Buy me a coffee Tweet ShareData in SwiftUI, Part 1: Data
Part 1 in a series on understanding data in SwiftUI. In the first part, we will try to understand the importance of data and how they play an essential role in SwiftUI.
Data in SwiftUI, Part 3: Tools
The last part in a series on understanding data in SwiftUI. See all tools SwiftUI provided to declare different types of data and dependency. Learn when and how to use @State, @Binding, ObservableObject, @ObservedObject, @EnvironmentObject, and @Environment.