@BindableObject 对 didChange.send() 的异步调用不会使其视图无效(并且永远不会更新)
Posted
技术标签:
【中文标题】@BindableObject 对 didChange.send() 的异步调用不会使其视图无效(并且永远不会更新)【英文标题】:@BindableObject async call to didChange.send() does not invalidate its view (and never updates) 【发布时间】:2019-07-10 11:23:14 【问题描述】:我发现我认为是@ObjectBinding 中的一个错误。对于 @BindableObject 异步调用其 didChange.send() 的情况,有时依赖于该更改的视图不会失效,因此它们的主体不再被请求,它们的外观也不会更新。
List
视图中的行应该每秒更新一次。起初它工作正常。但是,当使用“+”按钮添加新行时,事情开始横向发展。
我使行可点击,所以当它们被点击时,@State 变量会改变以改变文本的颜色。由于正确检测到此绑定,因此视图无效并且其外观发生变化。这表明计时器实际上正在运行,即使视图在被点击后才显示它。
请注意,以下代码的唯一目的是演示这种奇怪的行为。我不是在寻找解决方法。带着这个问题,我的目的是确认这是否是一个错误,如果不是,我做错了什么。
在某些其他情况下,将 @ObjectBinding 替换为 @EnvironmentObject 可以解决此问题。但在这种情况下,它只会有一点改善。
我在回答另一个问题时遇到了这个问题: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()
【问题讨论】:
【参考方案1】:您需要将 didChange 替换为 let objectWillChange = ObservableObjectPublisher()
,因为 ObservableObject 已经隐式实现了 PassthroughtSubject。
此外,Apple 文档现在建议使用 @Published 而不是 didSet:@Published var value: Int = 1
在您的更新函数中,将 self.update() 替换为 self.objectWillChange.send()
我发现 this link 解释了如何触发视图失效。
【讨论】:
非常感谢您的回答。我知道 ObservableObject 的变化。这是一个古老的问题(7 月 10 日)。我应该更新它或完全删除它。我已经忘记了。感谢您引起我的注意!干杯。以上是关于@BindableObject 对 didChange.send() 的异步调用不会使其视图无效(并且永远不会更新)的主要内容,如果未能解决你的问题,请参考以下文章
不符合协议 BindableObject - Xcode 11 Beta 4
WPF - 为啥在 XAML 中设置 Binding BindableObject.Text 时 SetProperty() 不触发 CanExecute?
解析 NSBlockOperation 的 executionBlocks