如果我们将UIlabel提供给GCD或NSOperationQueue中的后台线程会发生什么

时间:2016-04-06 02:42:57

标签: ios concurrency grand-central-dispatch nsoperationqueue

我在接受采访时被问到这个问题。我想知道如果我们将-webkit-transform: translateZ(0); -webkit-backface-visibility: hidden; 提供给后台线程会是什么情况。

2 个答案:

答案 0 :(得分:2)

简短的回答是"结果未定义"或"坏事"。 UIKit不是线程安全的,所以你不知道,但它不会很好。

我已经看到UI更改需要一个LOOOOOONNNG时间才能生效,如果有的话,我已经看到了崩溃。

更好的答案是"不要这样做。"

答案 1 :(得分:2)

这取决于标签是否在视图层次结构中。一般规则是后台线程运行的代码不应该触发任何UI更新,例如view.addSubviewlabel.setNeedsLayout等,那么在该线程中使用您的标签是安全的。

你应该小心,一旦将标签添加到视图中,即使在后台线程中更新label.text也是危险的,因为它会使其superview的布局无效,因此UI将在该线程内得到更新。

假设您的自定义UILabel类在其构造函数中执行一些耗时的操作,这与UI无关:

class MyFatLabel: UILabel {
  override init(frame: CGRect) {
    super.init(frame: frame)
    self.text = "Lorem ipsum"        
    self.readDataFromDisk() // will block the main thread.
  }
}

然后,您可以在单独的线程中初始化该标签,并将其添加到主(UI)线程中的视图中,以便用户与UI的交互不会被阻止:

dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
  let label = MyFatLabel(frame: CGRectZero)

  dispatch_async(dispatch_get_main_queue()) {
    view.addSubview(label)
  }
}

简而言之,您可以在后台线程中初始化新的UILabel(或任何UIResponder),但是,您应该更改其主要线程内触发UI更新的任何属性。