美文网首页
@State 介绍

@State 介绍

作者: xiaofu666 | 来源:发表于2023-02-24 15:10 被阅读0次

可以读取和写入由SwiftUI管理的值的属性包装类型。

SwiftUI管理声明为状态的属性的存储。当值更改时,SwiftUI会更新视图层次结构中取决于该值的部分。使用状态作为存储在视图层次结构中的给定值的唯一真实来源。

“State”实例不是值本身;这是一种读写价值的方法。要访问状态的基础值,请通过其属性名称引用它,该属性名称返回“state/wrappedValue”属性值。例如,可以通过直接引用属性来读取和更新“PlayButton”视图中的“isPlaying”状态属性:

  struct PlayButton: View {
      @State private var isPlaying: Bool = false
 
      var body: some View {
          Button(isPlaying ? "Pause" : "Play") {
              isPlaying.toggle()
          }
      }
  }

如果将状态属性传递给子视图,SwiftUI会在父视图中的值发生更改时随时更新子视图,但子视图不能修改该值。要使子视图能够修改存储的值,请改为传递“绑定”。您可以通过访问状态的“state/projectedValue”来获得状态值的绑定,这是通过在属性名称前加上美元符号(“$”)来获得的。

例如,您可以从上面的示例中的播放按钮中删除“正在播放”状态,而使按钮绑定到状态:

  struct PlayButton: View {
      @Binding var isPlaying: Bool
 
      var body: some View {
          Button(isPlaying ? "Pause" : "Play") {
              isPlaying.toggle()
          }
      }
  }

然后,您可以定义一个播放器视图,该视图声明状态,并使用美元符号前缀创建对状态的绑定:

  struct PlayerView: View {
      var episode: Episode
      @State private var isPlaying: Bool = false
 
      var body: some View {
          VStack {
              Text(episode.title)
                  .foregroundStyle(isPlaying ? .primary : .secondary)
              PlayButton(isPlaying: $isPlaying) // Pass a binding.
          }
      }
  }

不要在视图层次结构中实例化视图的位置初始化视图的状态属性,因为这可能与SwiftUI提供的存储管理冲突。为了避免这种情况,总是将state声明为private,并将其放在视图层次结构中需要访问该值的最高视图中。然后将状态与任何也需要访问的子视图共享,可以直接用于只读访问,也可以作为读写访问的绑定。

您可以从任何线程安全地改变状态财产。

 @available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.0, *)
 @frozen @propertyWrapper public struct State<Value> : DynamicProperty {

     /// 使用初始包装值创建状态。
     ///
     /// 不要直接调用此初始值设定项。而是声明一个属性
     /// 使用“State”属性,并提供初始值:
     ///
     ///     @State private var isPlaying: Bool = false
     ///
     /// - 参数wrappedValue:状态的初始wrapped值。
     public init(wrappedValue value: Value)
    
     /// 使用初始值创建状态。
     ///
     /// - 参数值:状态的初始值。
     public init(initialValue value: Value)
    
     /// 状态变量引用的基础值。
     ///
     /// 此属性提供对值数据的主要访问。但是,您不能直接访问“wrappedValue”。而是引用使用“State”属性创建的属性变量。在下面的示例中,按钮的标签取决于“isPlaying”的值,其操作将切换“isPlayng”的值。这两个访问都隐式依赖于state属性的包装值。
     ///
     ///     struct PlayButton: View {
     ///         @State private var isPlaying: Bool = false
     ///
     ///         var body: some View {
     ///             Button(isPlaying ? "Pause" : "Play") {
     ///                 isPlaying.toggle()
     ///             }
     ///         }
     ///     }
     ///
     public var wrappedValue: Value { get nonmutating set }
    
     /// 状态值的绑定。
     ///
     /// 使用投影值将绑定值向下传递到视图层次结构。要获取“projectedValue”,请在属性变量前面加上美元符号(“$”)。在以下示例中,“PlayerView”使用“$isPlaying”将状态属性“isPlaying”的绑定投影到“PlayButton”视图:
     ///
     ///     struct PlayerView: View {
     ///         var episode: Episode
     ///         @State private var isPlaying: Bool = false
     ///
     ///         var body: some View {
     ///             VStack {
     ///                 Text(episode.title)
     ///                     .foregroundStyle(isPlaying ? .primary : .secondary)
     ///                 PlayButton(isPlaying: $isPlaying)
     ///             }
     ///         }
     ///     }
     ///
     public var projectedValue: Binding<Value> { get }
 }

相关文章

网友评论

      本文标题:@State 介绍

      本文链接:https://www.haomeiwen.com/subject/rzjxldtx.html