为什么捕获onChange(of:Perform:)的参数?

Why is parameter for onChange(of:perform:) captured?(为什么捕获onChange(of:Perform:)的参数?)

本文介绍了为什么捕获onChange(of:Perform:)的参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是onChange(of:perform:)SwiftUI修饰符。然后我想要获得旧的值,将其与新的值进行比较。我看了文档,上面写着:

闭包可以捕获上一个值以将其与新值进行比较。

举例:

.onChange(of: playState) { [playState] newState in
    model.playStateDidChange(from: playState, to: newState)
}
我的问题是,为什么在该示例中playState[ ]中被捕获?playState值无需传入即可轻松访问。此外,这不是类的一部分,所以我假设没有办法通过捕获某种类型的self来创建强引用。

为什么该示例是这样编写的?

推荐答案

在正常情况下,在不可变值类型(例如,astruct)中定义的闭包捕获其值,该值不会更改,因此一切正常。

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属性包装器访问值,该包装器将检索随后更新的值。

为了应对这种情况,您可以使用捕获列表将该属性捕获到闭包的局部变量中:

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显然是传入的带有新值的参数。

这篇关于为什么捕获onChange(of:Perform:)的参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:为什么捕获onChange(of:Perform:)的参数?