【问题标题】:Use cocoa bindings and threads使用可可绑定和线程
【发布时间】:2019-08-12 10:20:15
【问题描述】:

我有一些标签绑定到一些变量,这些变量通过 GCD 在其他线程中修改。
现在我读到可可绑定不是线程安全的,但我的应用程序运行良好(当变量的值在后台线程中更新时,UI 会更新)

这是在后台线程中进行计算的正确方法吗?如果我需要更改变量值,请通过

DispatchQueue.main.sync() {
   self.variable = newValue
}

? 如果 cocoa 绑定不是线程安全的,为什么我从来没有遇到任何崩溃,因为在后台进程写入值时“读取”绑定的 UI 元素?

将值绑定到 UI 元素(通过可可绑定)并通过异步线程修改它的首选方法是什么?

谢谢!

【问题讨论】:

  • 我的猜测是您立即更新线程,但主线程中值的更新由框架安排。即使都是一个线程,绑定也不一定是同步的。您可以在更新变量的行之前设置一个断点,然后当程序停在那里时,在 GCD 调度函数上设置符号断点。您可能会看到绑定代码为您调用 dispatch_async。见this question。抱歉,ObjC 而不是 Swift。
  • @stevesliva KVO 和绑定是同步的。控件的视觉更新不是。

标签: multithreading cocoa grand-central-dispatch cocoa-bindings


【解决方案1】:

是的,如果你修改一个被 Cocoa 绑定观察到的对象,你应该只在主线程上这样做,而 GCD 将修改分派到主线程是一个很好的方法。

是的,您的应用可能在大多数情况下都能正常运行,但这可能是基于运气而不是实际正确的。问题是 Cocoa 绑定是基于 Key Value Observation 的,并且 KVO 通知发布在导致突变的线程上。

这也是一个复杂性问题。只要您的应用程序相对简单且快速,两个线程相互冲突的可能性就会小得多。想象一下,当您的应用程序变得更加复杂且计算量更大时......并且出现了一个问题......但此时您可能有数百个地方正在修改来自多个线程的绑定属性。从长远来看,只要遵守规则,就会让你免于悲痛。使用主线程更新绑定到对象并尝试将绑定属性保持为不可变的值语义类型。

【讨论】:

  • “尝试将绑定属性保留为不可变的值语义类型”为什么会这样?我将一些标签绑定到一个可变字典值(必须将其设置为 @objc 动态)并经常通过线程更新此字典值,而且我从未(多年来)在这里发生过任何崩溃。
  • @MikeNathas - 该评论与“我多年来一直以这种方式清洁枪支并且还没有开枪!”在同一个球场上。一个人可以做某事的事实并不意味着它是聪明去做的。你可能会毫无问题地做一千次,然后在那一千次也是第一次做一些微不足道的事情(或者更糟糕的是,你的一个队友会这样做),然后发现自己需要半个月的调试才能找出问题所在.只是说...
  • 限制绑定到不可变的值语义类型并不是绝对必要的(并且某些地方必须是可变的,值才能改变),但是使用不可变的值语义类型消除了一种可能的途径,特别是隐蔽且难以调试的错误。这是一个最佳实践,而不是“规则”本身。
  • 也不确定如何看待这个绑定到不可变值没有意义(我可以简单地添加一个固定标签)
  • 是的。我的意思是你的可变字典中的值应该是不可变的。即使用NSString 而不是NSMutableString。如果其他东西改变了可变字符串,你的绑定几乎肯定会不会更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 2011-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多