NSArrayController在后台线程

时间:2016-07-29 11:11:37

标签: multithreading cocoa binding nsarraycontroller

情况如下:

  • NSTableView绑定到NSArrayController
  • NSArrayController绑定到AnalysisResult对象数组

    dynamic var analysisResults: [AnalysisResult] = [AnalysisResult]() // model for table view via resultsArrayController
    
  • NSTableView有一列"结果"绑定到AnalysisResult.value

现在,当用户点击某个按钮时,它会在后台线程中触发分析,并修改" analysisResults"中的对象。它不会添加或删除数组中的任何对象。它只会改变"值" AnalysisResult对象的属性。

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
        for (index, curAnalysisRes) in self.analysisResults.enumerate() {
            curAnalysisRes.value = "some new value" // simplified but the value can be updated in many different places of the algorithm
        }
        dispatch_sync(dispatch_get_main_queue()) {
            /* Ask the tableview to reload data in main UI thread */
            self.myTableView.reloadData()
        }
    }

分析后,要求UI线程更新表格视图。

但问题是:我收到以下警告:

  CoreAnimation: warning, deleted thread with uncommitted CATransaction; created by:
  0   QuartzCore                          0x00007fff8f06369a _ZN2CA11Transaction4pushEv + 318
  1   QuartzCore                          0x00007fff8f06319a _ZN2CA11Transaction15ensure_implicitEv + 276
  2   QuartzCore                          0x00007fff8f069719 _ZN2CA5Layer13thread_flags_EPNS_11TransactionE + 37
  3   QuartzCore                          0x00007fff8f069668 _ZN2CA5Layer4markEPNS_11TransactionEjj + 64
  4   QuartzCore                          0x00007fff8f06b12b _ZN2CA5Layer25set_needs_display_in_rectERK6CGRect + 333
  5   QuartzCore                          0x00007fff8f06afdc -[CALayer setNeedsDisplayInRect:] + 25
  6   AppKit                              0x00007fff872d12e8 _NSBackingLayerSetNeedsDisplayInRect + 319
  7   AppKit                              0x00007fff872d11a3 -[_NSBackingLayer setNeedsDisplayInRect:] + 61
  8   QuartzCore                          0x00007fff8f06af9d -[CALayer setNeedsDisplay] + 62
  9   AppKit                              0x00007fff872d198b -[NSView(NSInternal) _setLayerNeedsDisplayInViewRect:] + 606
  10  AppKit                              0x00007fff8729f88e NSViewSetNeedsDisplayInRect + 945
  11  AppKit                              0x00007fff8729f4d6 -[NSView setNeedsDisplayInRect:] + 48
  12  AppKit                              0x00007fff8729f2ed -[NSView setNeedsDisplay:] + 81
  13  AppKit                              0x00007fff872f2be1 -[NSTextFieldCell setObjectValue:] + 88
  14  AppKit                              0x00007fff873e3026 -[NSControl setObjectValue:] + 135
  15  AppKit                              0x00007fff873ce0c6 -[_NSPlaceholderTextFieldPlugin showValue:inObject:] + 110

警告是由修改绑定到arraycontroller的数组引起的。 我不想在主线程中执行分析,因为它冻结了UI。

如何避免警告?

1 个答案:

答案 0 :(得分:0)

好的,我在这里找到了解决方案,而且非常简单。

由于我正在修改绑定到NSArrayController的数组的值,并且因为控制器绑定到NSTableView(因此与UI相关),所以我显然不在主UI线程中做UI内容。

从技术上讲,由于cocoa绑定使用KVO(键值观察),因此我在数组中进行修改而触发的更改通知会在非UI线程中传播,从而导致上次提及的消息:

CoreAnimation: warning, deleted thread with uncommitted CATransaction;

此外,一个有趣的副作用,代码片段:

self.myTableView.reloadData()

不再需要了,因为KVO通知现在可以在UI线程中正确传播。