可以读取和写入由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 }
}
网友评论