【问题标题】:NSArrayController backed array modification in background threadNSArrayController 在后台线程中支持数组修改
【发布时间】:2023-03-03 22:57:01
【问题描述】:

情况如下:

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

    dynamic var analysisResults: [AnalysisResult] = [AnalysisResult]() // model for table view via resultsArrayController
    
  • NSTableView 有一列“result”绑定到 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

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

如何避免警告?

【问题讨论】:

    标签: multithreading cocoa binding nsarraycontroller


    【解决方案1】:

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

    由于我正在修改绑定到 NSArrayController 的数组的值,并且由于控制器绑定到 NSTableView(因此与 UI 相关),因此我显然不是在主 UI 线程中执行 UI 的东西。

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

    CoreAnimation: warning, deleted thread with uncommitted CATransaction;
    

    此外,还有一个有趣的副作用,即这段代码:

    self.myTableView.reloadData()
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-04
      • 2016-04-29
      • 1970-01-01
      • 2021-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多