Swift 语言和 Swift 属性包装器,`nonmutating set` 有什么用?

问题描述 投票:0回答:1

在 SwiftUI 中,@State 定义为:

@frozen @propertyWrapper public struct State<Value> : DynamicProperty {

它有一个计算属性:

    public var wrappedValue: Value { get nonmutating set }

问题:

  1. 为什么
    wrappedValue
    不需要实现getter和setter?这是什么简写语法?
  2. nonmutating set
    的意图是什么?它是否试图禁用设置器?
  3. 围绕
    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
传递给另一个函数可以改变调用站点的某些值吗?为什么?

swift swiftui property-wrapper
1个回答
0
投票
  1. 这就是公开声明,实现是私有且隐藏的。
  2. 这是因为 setter 没有更改该结构的值,setter 只是将集合转发到内部对象中。
  3. 我不清楚你在问什么,但提到 $ 语法是 Binding(get: { }, set: { }) 的糖可能会有所帮助,即一对 2 闭包。
© www.soinside.com 2019 - 2024. All rights reserved.