我发现我认为@ObjectBinding中的错误。对于@BindableObject异步调用其didChange.send()的情况,有时依赖于该更改的视图不会失效,因此不再请求它们的主体,并且不更新其外观。
List
视图中的行应该每秒更新一次。起初它工作正常。但是,当使用“ +”按钮添加新行时,事情开始横摆。
我将行设置为 tappable ,因此,当点击它们时,@ State变量会更改以更改文本的颜色。因为已正确检测到此绑定,所以该视图将无效并且其外观也会更改。这表明计时器实际上正在运行,即使该视图在被点击之前也没有显示。
请注意,下面代码的唯一目的是演示这种奇怪的行为。我不是在寻找解决方法。出于这个问题,我的目的是确认这是否是错误,如果不是,那我在做什么错。
在其他情况下,用@EnvironmentObject替换@ObjectBinding可以解决此问题。不过,在这种情况下,它只会有所改善。
我在回答另一个问题时遇到了这个问题:SwiftUI and Combine not working smoothly when downloading image
更新:顺便说一句,如果将@ObjectBinding替换为@State,一切将会顺利进行。
import SwiftUI
import Combine
struct Row: Equatable {
let id: Int
let name: String
}
struct ContentView : View {
@State private var rows: [Row] = [Row(id: 0, name: "Row #0"), Row(id: 1, name: "Row #1")]
var body: some View {
NavigationView {
List(rows.identified(by: \.id)) { row in
RowView(row: row, rowData: RowData())
}
.navigationBarItems(trailing:
Button(action: {
self.addRow()
}, label: {
Text("+").font(.system(size: 36.0))
}))
}
}
func addRow() {
rows.append(Row(id: rows.count, name: "Row #\(rows.count)"))
}
}
struct RowView: View {
let row: Row
@ObjectBinding var rowData: RowData
@State private var showBlue = false
var body: some View {
Text("\(row.name) - Seconds \(rowData.value)").foregroundColor(showBlue ? Color.blue : Color.primary)
.tapAction {
self.showBlue.toggle()
}
}
}
class RowData: BindableObject {
var didChange = PassthroughSubject<Void, Never>()
var value: Int = 1 {
didSet { didChange.send() }
}
init() {
update()
}
func update() {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
self.value += 1
self.update()
}
}
}
答案 0 :(得分:1)
您需要用let objectWillChange = ObservableObjectPublisher()
替换didChange,因为ObservableObject已隐式实现了PassthroughtSubject。
此外,Apple文档现在建议使用@Published代替didSet:@Published var value: Int = 1
在您的更新函数中,将self.update()替换为self.objectWillChange.send()
我发现this link解释了如何触发视图无效。