SwiftUI Data Flow |Part 1|
SwiftUI is interesting. You can create complicated views very easily. However, maintaining data flow between those views can be daunting or that’s something I feel.
This article will be a simple guid to swiftUI data flow. I will try to explain a couple of property wrapper to send, get back, read-write data in swiftUI.
Property Wrapper
Property wrapper, wraps a value and gives it additional behaviour to act on. SwiftUI has it’s own property wrappers, however we can also create our own if we like. For this article, we’ll be talking about the following property wrappers:
- @State
- @Binding
- @ObservableObject
- @Published
- @EnvironmentObject
@State
When we need to store small of data for a view, we can use the @State property wrapper. The data types can be int, bool, string or even struck. It automatically refreshes views that use that data as the value changes. State owns it’s data. Let’s look at an example:
Here we have a swiftUI view named Counter. As you can see, it has a state variable called number. In the body, we have a text that shows the number and a button that increments that number by 1.
Run it in the canvas preview and you’ll see the following result:
Here’s the interesting part. The Increment button adds 1 to the previous number and the Text view displays the updated value instantly.
@Binding
What if we want to access the state variable from another view. That’s where binding comes in. It can read and write to the binded state variable.
Here we have a child view inside our parent Counter view named IncrementButtonView. We need to change the number variable from the child view. In order to do that, we create a binding variable inside the IncrementButtonView and while creating an instance of it we pass the state variable to it with a dollar sign attached to it and Voilà! Now, the numb property gets the read write control over the number property.
As you can see, the result is same. However this time the increment is happening from another view.
Note something, binded property does not own the data but state property does. Here IncrementButtonView doesn’t own the data it’s changing. It’s parent view or Counter owns the data.
@ObservableObject
Sometimes while building an app, we need value/values that multiple views depends on. For example, if your have a subscription plan and features are unlocked based on subscription, you need to check isSubscribed for the views that needs it. In this case, we can make use of an ObservableObject.
We have a class and it confirms to ObservableObject protocol. Inside this class we have a boolean variable isSubscribed. Unless we mark it with @Published property wrapper, it will not broadcast the value change. To use the class while creating a variable, it needs to use @ObservedObject property wrapper. By doing so, it can listen to and write to the Published variables.
As you can see, the HomeView shows result based on the observed object. If we change the value, it’ll also reflect on the Text view.
However, we want multiple views to listen to the same instance of the Subscription class. How do we do that?
@EnvironmentObject
We can set an EnvironmentObject for a view and pass the object when the view was created. This was, the multiple views will be able to access and write to the same instance of the class.
Here when the app starts, it shows two view and we pass the subscription variable to both of then as an environmentObject. Then we declare the HomeView and SubscriptionView as follow:
Finally run the app and see the result.
Both are independent views, but they can read write to the same data. Also their view elements are updated according to the changed values.
I try to write articles about things I learn. Naturally, there will be mistakes even though I try my best to lessen them. So, feel free to let me know if there’s anything wrong.