为什么捕获 onChange(of:perform:) 的参数?
Why is parameter for onChange(of:perform:) captured?
我使用的是 onChange(of:perform:)
SwiftUI 修饰符。然后我想获得旧值,将其与新值进行比较。我阅读了文档,上面写着:
The previous value may be captured by the closure to compare it to the new value.
举个例子:
.onChange(of: playState) { [playState] newState in
model.playStateDidChange(from: playState, to: newState)
}
我的问题是为什么示例中的playState
是在[ ]
中捕获的? playState
值无需传入即可轻松访问。此外,这不是 class 的一部分,因此我认为无法通过捕获 [=15= 来创建强引用] 某种形式。
为什么例子要这样写?
在“正常”情况下,在不可变 value-type(例如 struct
)中定义的闭包捕获其值,该值不会改变,所以一切都很好。
struct Foo {
var a = "original"
func makeFn() -> () -> Void {
return { print(a) }
}
}
var foo = Foo()
let fn = foo.makeFn()
foo.a = "changed"
fn() // "original"
但是对于 @State
,实际值存储在 SwiftUI 维护的一些全局存储中,因此它基本上表现得好像它具有引用语义。
当调用闭包时,状态值已经改变,所以像上面那样做 print(a)
通过 @State
属性 包装器访问一个值,它检索 then-updated值。
为了解决这个问题,您可以使用捕获列表将 属性 捕获到闭包的局部变量中:
return { [a] in print(a) }
这当然是一个简化的示例,SwiftUI 可能在幕后做其他事情,但我认为它传达了这一点。
要查看 SwiftUI 中的差异,请尝试以下操作:
.onChange(of: playState) { [playState] newState in
print(playState, self.playState, newState)
}
输出将是这样的:
original new new
playState
是定义闭包时捕获的局部变量(即计算 body
时),self.playState
通过 @State
访问该值,这已经改变了,newState
显然是具有新值的passed-in参数。
我使用的是 onChange(of:perform:)
SwiftUI 修饰符。然后我想获得旧值,将其与新值进行比较。我阅读了文档,上面写着:
The previous value may be captured by the closure to compare it to the new value.
举个例子:
.onChange(of: playState) { [playState] newState in
model.playStateDidChange(from: playState, to: newState)
}
我的问题是为什么示例中的playState
是在[ ]
中捕获的? playState
值无需传入即可轻松访问。此外,这不是 class 的一部分,因此我认为无法通过捕获 [=15= 来创建强引用] 某种形式。
为什么例子要这样写?
在“正常”情况下,在不可变 value-type(例如 struct
)中定义的闭包捕获其值,该值不会改变,所以一切都很好。
struct Foo {
var a = "original"
func makeFn() -> () -> Void {
return { print(a) }
}
}
var foo = Foo()
let fn = foo.makeFn()
foo.a = "changed"
fn() // "original"
但是对于 @State
,实际值存储在 SwiftUI 维护的一些全局存储中,因此它基本上表现得好像它具有引用语义。
当调用闭包时,状态值已经改变,所以像上面那样做 print(a)
通过 @State
属性 包装器访问一个值,它检索 then-updated值。
为了解决这个问题,您可以使用捕获列表将 属性 捕获到闭包的局部变量中:
return { [a] in print(a) }
这当然是一个简化的示例,SwiftUI 可能在幕后做其他事情,但我认为它传达了这一点。
要查看 SwiftUI 中的差异,请尝试以下操作:
.onChange(of: playState) { [playState] newState in
print(playState, self.playState, newState)
}
输出将是这样的:
original new new
playState
是定义闭包时捕获的局部变量(即计算 body
时),self.playState
通过 @State
访问该值,这已经改变了,newState
显然是具有新值的passed-in参数。