Data Handling related to layout in SwiftUI (part 1)
About @State, @ObservedObject, @EnvironmentObject
This article was written under the following system environment:
- macOS Catalina Version 10.15
- Xcode Version 12.0
TL;DR,
I. Preparation: What needs for Swift UI Programming
II. @State, @ObservedObject, @EnvironmentObject
I. Preparation: What needs for Swift UI Programming
Please refer to the following article and see the topic “I. Preparation: What needs for Swift UI Programming” in the article
II. @State, @ObservedObject, @EnvironmentObject
The SwiftUI has a mechanism to automatically update the views that reference the data when the data is updated.
Views in the SwiftUI are defined as a struct, which is a value type. As it is, we can’t change the properties defined in a structure in the “var body”, which is a computed type property.
For example, the following code can’t change View.
If we want to manage the state of the view with the SwiftUI, we need to delegate the View state management to the SwiftUI framework using the following Property Wrappers.
And these three attributes have the mechanism to manage values related to the View and to recompute and redraw Views when the value is changed.
These are three basic custom attributes that can be used when declaring properties.
@State
@ObservedObject
@EnvironmentObject
When adding these attributes to View’s property, these data instances will be observed by SwiftUI. Then, as these properties are changed, these related Views automatically are changed.
These custom attributes have the method to automatically synchronize the property values with the state of the UI.
First, let’s see how to use the three basic attributes that SwiftUI provides.
II-A. @State
1. How to use @State
When adding @State
attribute to a property, the property can be the state variable.
Then the above code will work well.
Simply speaking, in the above code, @State
changes isShow
variable to the state value which SwiftUI can manage. So SwiftUI View can catch the isShow
value changing.
2. How to share @State property with another View
We can pass the state value to which added @State
, into other descendant’s Views.
Create two Views. One is main-View. Another is sub-View.
And the sub-View have a @Binding
property.
Then the sub-View is instantiated in the main-View.
Both @Binding
property in sub-View and @State
property is main-View are referring to the same instance in the above code. That’s why the main-View state value can be shared with the sub-View.
One of the features of @State
is that it makes it easy to work with simple data. And we can share the data with other descendent’s Views by linking it with a property with @Binding
.
If we want to pass a lot of data at once, it’s more convenient to use @ObservedObject
.
II-B. @ObservedObject
1. How to use @ObservedObject
An instance of the data class which declared @OvservedObject,
will be observed by the SwiftUI. And the View related to the instance will be automatically redrawn when the property is updated.
[Steps to use ObservedObject]
1. Create a new class that conforms “ObservableObject” protocol.
2. In the class, create some property that has the @Published
attribute.
3. In the View struct where the data is used set the property that attached@ObservedObject
on, and the property needs to conform to the class which we created.
1. This is a simple example code with @ObservedObject.
2. Using different data class instance
We can create different data class instances at the same time from one data class.
When sharing the same data property as @ObservedObject, it needs to refer to the same data class instance.
This is the separate instances created from one data class.
These data inherits from “1. This is a simple example code with @ObservedObject.”
3. Using the same data class instance
4. Using the same data class instance in different Views
5. Complexed Case with @ObservedObject
II-C. @EnvironmentObject
@EnvironmentObject
can share the same data class instance without passing the instance between Views.
[Steps to use EnvironmentObject]
1. Create a data class conform to “ObservableObject” protocol.
2. In the class, create some property that has the “@Published” attribute.
3. In the View struct where the data is used set the property that attached “@EnvironmentObject”, and the property needs to conform to the class which we created.
4. Use “environmentObject” modifier at the original View where we want to start to handle data.
If you create the data class instance with “environmentObject” modifier in “SceneDelegate.swift”, the class data can be used from the beginning of the App running.