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 throughStateTo drive, when the declared property is used@StateAfter 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@StateA 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@BingdingThrough the@BindingYou 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.