Blockchain ク gainst to the list
This article uses the current latest version of Xcode 12 + macOS Big sur + iOS14
Understand @ State
@state is an attribute modifier symbol used to read and write data managed by SwiftUI. When the @state tag changes in value, the page recalculates the body content.
Here’s a simple weather APP to illustrate:
-
Create an Image to display the weather
var body: some View { ZStack { VStack { Image(systemName: "sun.max.fill") .renderingMode(.original) .resizable() .frame(width: 100, height: 100, alignment: .center) .shadow(radius: 1)}}}Copy the code
-
Weather conditions are not fixed, do not write the name of the picture, change the name of the picture to a variable.
var weather = "sun.max.fill" var body: some View { . Image(systemName: weather) . } Copy the code
-
Add a few buttons below the image to modify the current weather.
let contents = ["cloud.sun.fill"."sun.max.fill"."cloud.heavyrain.fill"."thermometer.sun.fill"] var weather = "sun.max.fill" var body: some View { ZStack { VStack { . HStack(spacing: 10) {ForEach(contents.indices){index in Button(action: {changeWeather(index: index)}, label: { Image(systemName: contents[index]) .renderingMode(.original) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 24, height: 24, alignment: .center) .frame(width: 64, height: 32) .background(Color(.systemGroupedBackground)) .clipShape(RoundedRectangle(cornerRadius: 16)) .shadow(radius: 1) }) } } .padding() } } } func changeWeather(index: Int){}Copy the code
-
The effect is as follows:
-
Click the button to modify add:
func changeWeather(index: Int){ weather = contents[index] } Copy the code
The cashback report is wrong.
View is immutable. To modify the contents of a View, add a variable and add the @state modifier. Modify code:
@State var weather = "sun.max.fill"
Copy the code
The app works as expected:
SwiftUI is throughState
To drive, when the declared property is used@State
After modification, SwiftUI automatically manages the declared attribute and updates the page element using the attribute when it changes
@ the Binding to use
@bingding is a property modifier that can be used to read and write values from other data sources. Use @Binding to establish a bidirectional connection between the view that stores the data and the view that consumes it. For example, changing the value of the @binding modifier will also change the value of the @state attribute.
-
Next, modify the next app, add a new page and put the button to change the weather on the new page.
struct ControlPannel: View{ @State var weather: String let contents = ["cloud.sun.fill"."sun.max.fill"."cloud.heavyrain.fill"."thermometer.sun.fill"] var body: some View { HStack(spacing: 10) {ForEach(contents.indices){index in Button(action: {changeWeather(index: index)}, label: { Image(systemName: contents[index]) .renderingMode(.original) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 24, height: 24, alignment: .center) .frame(width: 64, height: 32) .background(Color(.systemGroupedBackground)) .clipShape(RoundedRectangle(cornerRadius: 16)) .shadow(radius: 1) }) } } .padding() } func changeWeather(index: Int){ weather = contents[index] } } Copy the code
-
The original page code is changed to:
var body: some View { ZStack { VStack { Image(systemName: weather) .renderingMode(.original) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 200, height: 200, alignment: .center) .shadow(radius: 1) ControlPannel(weather: weather) } } } Copy the code
-
You can’t change the weather icon by clicking the button
In the ControlPannel
@State
A new state is created. Any changes made in the ControlPannel only change the State of the ControlPannel, not the state of the original page. The tool for changing share status in SwiftUI is@Bingding
Through the@Binding
You can enable the ControlPannel to share the same State with the original page. -
Change @state in ControlPannel to @bingding:
struct ControlPannel: View{ @Binding var weather: String } Copy the code
-
Use the $sign to access the @state wrapper
var body: some View { ZStack { VStack { ... ControlPannel(weather: $weather) } } } Copy the code
Test it and it works fine:
conclusion
- If the page does not modify the data, we can use unmodifiable properties to store variables.
- @state to modify the attributes that the page needs to use.
- @binding to modify the @state property of other pages.