在 SwiftUI 中,@State 定义为:
@frozen @propertyWrapper public struct State<Value> : DynamicProperty {
它有一个计算属性:
public var wrappedValue: Value { get nonmutating set }
问题:
wrappedValue
不需要实现getter和setter?这是什么简写语法?nonmutating set
的意图是什么?它是否试图禁用设置器?nonmutating set
的问题有时会在以下片段中发生变化:struct PlayButtonStackOverflow: View {
@State private var isPlaying: Bool = false
var body: some View {
// TODO: 3.3: this does NOT change the state. why?
$isPlaying.wrappedValue = true
print($isPlaying.wrappedValue.description) // prints false
return Button(isPlaying ? "isPlaying = true" : "isPlaying = false") {
// TODO: 3.1: this does change the state.
$isPlaying.wrappedValue = true
// TODO: 3.1: and this prints true, why?
print($isPlaying.wrappedValue )
// `$isPlaying.wrappedValue` is accessing the State.projectValue, which is a Binding, and the Binding.wrappedValue has a non mutating setter. how come setter is actually mutating?
// TODO: 3.2: Compile error: Referencing property 'wrappedValue' requires wrapper 'Binding<Bool>'
// why? is there a way to access the State.wrappedValue setter? How is it being disabled?
// isPlaying.wrappedValue = true
}.padding()
}
}
更新A:
TODO 3.3
处的线给出了Modifying state during view update, this will cause undefined behavior.
这解释了其中的一部分。由于状态变化会触发身体再次评估。但在这种情况下,所有突变都是朝一个方向的。
问题 A.1:为什么
TODO 3.3
仍然打印 false?
问题 A.2:试图解决这个问题,
$isPlaying.wrappedValue = true
和 isPlaying = true
在第 TODO 3.3
行具有相同的效果吗?
问题 A.3:由于 Binding 是一个结构体,因此在创建它的副本时传递值类型。但在这种情况下,将
$isPlaying
传递给另一个函数可以改变调用站点的某些值吗?为什么?