【发布时间】:2020-03-10 12:42:40
【问题描述】:
我在 View 中使用了两个发布者:
A:String.publisher
B:ObservableObject 包含一个@Published String 类型
如果我监控发布者 A,我会得到一个无限循环。 但是监控发布者B是可以的!
import SwiftUI
import Combine
class Model: ObservableObject{
@Published var someBool = false
@Published var name:String = ""
}
struct ContentView: View {
// Publisher A
@State var name = ""
// Publisher B
@ObservedObject var model = Model()
var body: some View {
VStack {
// Plan A: lead to infinite loop!!!
TextField("Input Name", text: $name)
// Plan B: It's OK
//TextField("Input Name", text: $model.name)
.onReceive(name.publisher.reduce("", {t,c in
t + String(c)
})) {text in
print("change to \(text)")
self.model.someBool.toggle() //Plan A: infinite loop!!!
}
/*
.onReceive(model.$name){name in
print("change to \(name)")
self.model.someBool.toggle() //Plan B: It's OK!!!
}
*/
}
}
}
虽然我在onReceive()中改变了model.someBool的值,但是Plan B没问题,Plan A导致死循环。 这是为什么???谢谢:)
【问题讨论】:
-
从 "A" 中删除 self.model.someBool.toggle() 它将按预期工作。
-
我知道它成功了,但是为什么 Play B 也可以在没有删除 self.model.someBool.toggle() 的情况下工作???
-
@ObservedObject 在“B”中只通知 SwiftUI 一次,在“A”中,您有两个不同的“更新请求”,首先是因为状态变量发生了变化(通过输入文本字段),其次是模型修改.形成一个循环。
-
你的模型对状态作出反应,状态对模型作出反应,模型对状态作出反应.....
-
我也在为 .onReceive 的无限循环问题而苦苦挣扎。我可以使用上面作者的代码轻松复制无限循环——简单的复制粘贴到新的 SwiftUI 项目中,然后单击运行。问题是为什么编译后的代码会立即触发无限循环,甚至在用户在 TextField 中键入单个值之前。