以下测试代码有什么问题?当我在字段中输入一个字符时,didSet 进入一个递归循环。如果删除了 inout + &,则代码按预期运行,每次击键都会触发 didSet。同样,如果我删除了@Published,但保留了 inout 和 &,则不会发生 didSet 递归。
我为什么要这样做?我有一个表单字段类型(一个 4 char 十六进制字段),它需要通用处理,然后重新编码回基本结构。因此,目的是将所有公共代码抽象为一个函数,该函数在 ModelView 区域中设置每个 var 后触发。此代码只是重现该问题的最小示例。
看起来仅仅获取@published var 的地址就会触发关联的 didSet 。对此的解释是,即使没有进行任何更改,使用 inout总是会重新写入目标 var。
class A: ObservableObject
{
@Published var publishedVar = "abc" {
didSet {
print("didSet Triggered")
doNothing(commonText: &publishedVar)
}
}
private func doNothing(commonText: inout String)
{
}
}
struct ContentView: View {
@ObservedObject var a = A()
var body: some View {
TextField("dummy", text: $a.publishedVar)
}
}
如果相关,这是在 Mac 上运行 Catlina 作为 Mac 应用程序(不是 IOS 或模拟器)。Xcode 版本 12.4 (12D4e)
好的,我已经尝试在接收器上完成阅读并尝试遵循建议(下面更新了 A 类),现在我发现它在 doNothing 函数中递归。看起来我缺少一些基本的东西 8-(
class A: ObservableObject
{
var cancellable: AnyCancellable?
@Published var publishedVar: String = "def"
private func doNothing(commonText: inout String)
{
print("In doNothing \(commonText)")
}
init()
{
cancellable = $publishedVar.sink { value in
self.doNothing(commonText: &self.publishedVar)
print("saw sink \(value)")
}
}
}