首页 > 解决方案 > Swift macOS NSTableView 很慢

问题描述

我在 Swift (macOS) 中工作并且有一个 NSTableView,其内容绑定到一个 NSArrayController。tableView 单元格可以使用跨单元格的九列的字符串和 NSPopUpButtons 的混合来设置/编辑数据,这些列通过使用简单的 NSObject 子类(即具有@objc dynamic var属性)的绑定来管理。绑定似乎都有效,并且数据是正确的,但我注意到它变得非常慢,因为表的内容变得有点大(即几百个项目)。

此外,将应用程序置于后台并转换回前台会导致旋转轮挂起,其长度与 tableView 中的项目数相关。

有人对我从哪里开始尝试找出问题有任何提示吗?当我将 NSPopUpButtons 添加到某些单元格列时,似乎开始出现缓慢,但我不知道为什么会这样。NSPopUpButton 绑定是在 Interface Builder 中使用Value Selection -> Selected Value(在 Bindings Inspector 中)创建的。

更新:删除绑定没有区别。据我所知,更新 NSPopUpButtons 所花费的时间。这既令人惊讶又令人遗憾,因为它们确实是我正在做的最好的 UI 元素。

61.00 ms   81.3%    0 s                         -[NSTableCellView _windowChangedKeyState]
61.00 ms   81.3%    0 s                          -[NSView _windowChangedKeyState]
59.00 ms   78.6%    0 s                           -[NSPopUpButton _windowChangedKeyState]
59.00 ms   78.6%    0 s                            -[NSControl _windowChangedKeyState]
56.00 ms   74.6%    0 s                             +[NSAppearance _performWithCurrentAppearance:usingBlock:]
55.00 ms   73.3%    0 s                              __35-[NSControl _windowChangedKeyState]_block_invoke
24.00 ms   32.0%    0 s                               -[NSButton updateCell:]
22.00 ms   29.3%    0 s                               -[NSPopUpButtonCell _updateSubviewsInView:includeTitleTextField:]
21.00 ms   28.0%    0 s                                -[NSButtonCell _updateSubviewsInView:includeTitleTextField:]
18.00 ms   24.0%    0 s                                 -[NSButtonCell _updateBackgroundViewWithFrame:inView:]
10.00 ms   13.3%    0 s                                  -[NSButtonCell _bezelRectForBounds:inView:]
7.00 ms    9.3% 0 s                                  _NSSetObjectValueAndNotify
1.00 ms    1.3% 1.00 ms                                  DYLD-STUB$$objc_setProperty_atomic_copy
3.00 ms    4.0% 0 s                                 -[NSView setNeedsDisplay:]
1.00 ms    1.3% 0 s                                -[NSButtonCell _wantsSeparatedContentSubviewsInView:]
9.00 ms   12.0% 0 s                               -[NSButtonCell _windowChangedKeyStateInView:]

让这变得困难的另一件事是,当从后台出来时,在Instruments 注册应用程序中的任何活动之前似乎有一个暂停。这可能只是 Instruments 放弃焦点的事情......不确定,但这无济于事。上面的示例来自应用程序激活时的初始活动,但这并不代表延迟的整个持续时间,其中相当一部分显示 Instruments 中根本没有任何活动。

如果真的只是在 tableView 单元格列中使用 NSPopUpButtons 是一个坏主意,那么我将不得不改变我的设计,但如果有人有任何进一步的建议,我会很感激任何建议。

更新2:从暂停中获取更大的样本,实际上有很多时间花在其他地方(恐怕我对视图绘图的了解不够,无法准确理解这里发生了什么):

302.00 ms   99.0%   0 s      Main Thread  0x20adcd
302.00 ms   99.0%   0 s       start
302.00 ms   99.0%   0 s        main
302.00 ms   99.0%   0 s         NSApplicationMain
302.00 ms   99.0%   0 s          -[NSApplication run]
243.00 ms   79.6%   0 s           -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]
243.00 ms   79.6%   0 s            _DPSNextEvent
243.00 ms   79.6%   0 s             _BlockUntilNextEventMatchingListInModeWithFilter
243.00 ms   79.6%   0 s              ReceiveNextEventCommon
243.00 ms   79.6%   0 s               RunCurrentEventLoopInMode
243.00 ms   79.6%   0 s                CFRunLoopRunSpecific
243.00 ms   79.6%   0 s                 __CFRunLoopRun
243.00 ms   79.6%   0 s                  __CFRunLoopDoObservers
243.00 ms   79.6%   0 s                   __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__
243.00 ms   79.6%   0 s                    __65+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayRefresh]_block_invoke
243.00 ms   79.6%   0 s                     CA::Transaction::commit()
206.00 ms   67.5%   0 s                      CA::Context::commit_transaction(CA::Transaction*)
203.00 ms   66.5%   0 s                       CA::Layer::display_if_needed(CA::Transaction*)
102.00 ms   33.4%   0 s                        -[_NSViewBackingLayer display]
97.00 ms   31.8%    0 s                         _NSViewUpdateLayer
92.00 ms   30.1%    0 s                          -[NSButtonBezelView updateLayer]
91.00 ms   29.8%    0 s                           -[NSWidgetView updateLayer]
90.00 ms   29.5%    0 s                            _withOverlaidDictionary
90.00 ms   29.5%    0 s                             __27-[NSWidgetView updateLayer]_block_invoke
90.00 ms   29.5%    0 s                              -[NSAppearance _createOrUpdateLayer:options:]
90.00 ms   29.5%    0 s                               -[NSCompositeAppearance _callCoreUIWithBlock:options:]
88.00 ms   28.8%    0 s                                CUICreateOrUpdateLayer
88.00 ms   28.8%    0 s                                 CUIRenderer::CreateOrUpdateLayer(__CFDictionary const*, CALayer**)
85.00 ms   27.8%    0 s                                  CUICoreThemeRenderer::CreateOrUpdateLayer(CUIDescriptor const*, CALayer**)
81.00 ms   26.5%    0 s                                   CUICoreThemeRenderer::CreateOrUpdateLayerSimple(CUIRenditionKey*, CUIDescriptor const*, CALayer**)
74.00 ms   24.2%    0 s                                    -[CUIThemeFacet updateLayer:effects:]
71.00 ms   23.2%    0 s                                     -[CUIShapeEffectStack newFlattenedImageFromShapeCGImage:withScale:cache:]
37.00 ms   12.1%    0 s                                      -[CIContext createCGImage:fromRect:format:colorSpace:deferred:]

最后更新:是的,似乎 NSPopUpButton 确实是问题所在。太糟糕了。我将弹出窗口从 tableView 中移出,而是使用它们来更新所选 tableView 单元格中的列(只是 textFields)。速度问题消失了。

标签: swiftmacosnstableviewcocoa-bindingsnsarraycontroller

解决方案


推荐阅读