swift - 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)。速度问题消失了。
解决方案
推荐阅读
- reactjs - 如何在 `proseMirror` 编辑器中使用`react-hook-form`?
- c# - 如何从 Blazor 中的不同 API 路由获取另一个列表的列表?
- java - 在 java 中使用 ArrayList 设计堆栈时出错
- c# - 如何以编程方式在 UWP 应用程序中一次按下组合键
- mysql - 在另一个实体中多次使用同一个实体
- deep-learning - 我们可以使用两个相同的深度神经网络,中间的函数成本是多少
- git - 根据合并请求重命名分支
- swift - config 2 alerts messages in button swiftUI
- python - Python - 获取顶级域名
- shopware - Shopware 6 sw-entity-单选空选项