调整大小时 NSWindow 重绘 issues/flickers
NSWindow redraw issues/flickers when resized
我最近注意到当我调整应用 window.
大小时,我的应用中的某些控件(NSTableView 和 NSOutlineView)会闪烁
我不明白为什么会这样。我将应用程序缩减到最低限度:一个文档 window 控制器和一个包含大纲视图和按钮的 window。无后台处理,不加载文档数据等
这里是显示 UI 调整 window 大小时片段的屏幕截图:
注意顶部轮廓视图的片段、白色背景和偏移 window 阴影。
控制台中还有与 Core Graphics 相关的警告(见下文)。不确定是否与问题有关。
应用 运行 Mac OS X 10.10.1,部署目标和基本 SDK 设置为 10.9。
控制台输出(不是崩溃):
<Warning>: void CGSUpdateManager::log() const: conn 0x22833 token 0x10dfffffffff3823
<Warning>: Backtrace (at 4250.73):
<Warning>: void CGSUpdateManager::log() const: 0 CoreGraphics 0x00007fff986f5215 CGSBacktraceCreate + 59
<Warning>: void CGSUpdateManager::log() const: 1 CoreGraphics 0x00007fff98714688 _ZN16CGSUpdateManager14disable_updateEv + 84
<Warning>: void CGSUpdateManager::log() const: 2 AppKit 0x00007fff8e4e2de5 -[NSWindow disableScreenUpdatesUntilFlush] + 127
<Warning>: void CGSUpdateManager::log() const: 3 AppKit 0x00007fff8e4a2250 -[NSView _gainedLayerTreeHostAncestor] + 385
<Warning>: void CGSUpdateManager::log() const: 4 AppKit 0x00007fff8e4a20ae -[NSView _recursiveGainedLayerTreeHostAncestor] + 27
<Warning>: void CGSUpdateManager::log() const: 5 AppKit 0x00007fff8e4a667a -[NSScroller _recursiveGainedLayerTreeHostAncestor] + 103
<Warning>: void CGSUpdateManager::log() const: 6 AppKit 0x00007fff8e70da56 -[NSScroller _setSurfaceBacked:] + 213
<Warning>: void CGSUpdateManager::log() const: 7 AppKit 0x00007fff8e67324f -[NSScrollView setScrollerStyle:] + 304
<Warning>: void CGSUpdateManager::log() const: 8 AppKit 0x00007fff8ed0af27 +[NSScrollerImpPair _updateAllScrollerImpPairsForNewRecommendedScrollerStyle:] + 426
<Warning>: void CGSUpdateManager::log() const: 9 CoreFoundation 0x00007fff8b36fcbc __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
<Warning>: void CGSUpdateManager::log() const: 10 CoreFoundation 0x00007fff8b2611b4 _CFXNotificationPost + 3140
<Warning>: void CGSUpdateManager::log() const: 11 Foundation 0x00007fff8b5f8ea1 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
<Warning>: void CGSUpdateManager::log() const: 12 CoreFoundation 0x00007fff8b2d154c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
<Warning>: void CGSUpdateManager::log() const: 13 CoreFoundation 0x00007fff8b2c3655 __CFRunLoopDoBlocks + 341
<Warning>: void CGSUpdateManager::log() const: 14 CoreFoundation 0x00007fff8b2c2e0e __CFRunLoopRun + 910
<Warning>: void CGSUpdateManager::log() const: 15 CoreFoundation 0x00007fff8b2c2838 CFRunLoopRunSpecific + 296
<Warning>: void CGSUpdateManager::log() const: 16 HIToolbox 0x00007fff9980043f RunCurrentEventLoopInMode + 235
<Warning>: void CGSUpdateManager::log() const: 17 HIToolbox 0x00007fff998000be ReceiveNextEventCommon + 179
<Warning>: void CGSUpdateManager::log() const: 18 HIToolbox 0x00007fff997ffffb _BlockUntilNextEventMatchingListInModeWithFilter + 71
<Warning>: void CGSUpdateManager::log() const: 19 AppKit 0x00007fff8e4266d1 _DPSNextEvent + 964
<Warning>: void CGSUpdateManager::log() const: 20 AppKit 0x00007fff8e425e80 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 194
<Warning>: void CGSUpdateManager::log() const: 21 AppKit 0x00007fff8e419e23 -[NSApplication run] + 594
<Warning>: void CGSUpdateManager::log() const: 22 AppKit 0x00007fff8e4052d4 NSApplicationMain + 1832
<Warning>: void CGSUpdateManager::log() const: 23 MyApp 0x00000001000022eb main + 75
<Warning>: void CGSUpdateManager::log() const: 24 libdyld.dylib 0x00007fff97a025c9 start + 1
作为参考,我找到了根本原因,虽然我无法解释。
在 applicationDidFinishLaunching:
中,我正在初始化一个 window 控制器的共享实例,并通过调用 showWindow:nil
显示它的 window。 window 恰好包含一个 NSTableView
。此 table 视图导致其他大纲视图中的闪烁(在不相关的 window 中)。
为什么?老实说,我不知道。我从 window 中删除了所有控件,并直接从 Interface Builder 面板添加了一个空的 table 视图 → 出现问题。删除 table 视图后问题消失了。
解决方案是不要在 applicationDidFinishLaunching:
中立即打开 window。相反,我添加了一个菜单以便稍后打开它(它是一个带有调试信息的 window)。
我的解决方案是在非常小的延迟后将 window 置于前面,即:
- (void)awakeFromNib {
if (WSPreferences.currentApplication.showActivityWindow) {
//
//
[self performSelector:@selector(makeKeyAndOrderFront:) withObject:self afterDelay:0.1];
}
}
我最近注意到当我调整应用 window.
大小时,我的应用中的某些控件(NSTableView 和 NSOutlineView)会闪烁我不明白为什么会这样。我将应用程序缩减到最低限度:一个文档 window 控制器和一个包含大纲视图和按钮的 window。无后台处理,不加载文档数据等
这里是显示 UI 调整 window 大小时片段的屏幕截图:
注意顶部轮廓视图的片段、白色背景和偏移 window 阴影。
控制台中还有与 Core Graphics 相关的警告(见下文)。不确定是否与问题有关。
应用 运行 Mac OS X 10.10.1,部署目标和基本 SDK 设置为 10.9。
控制台输出(不是崩溃):
<Warning>: void CGSUpdateManager::log() const: conn 0x22833 token 0x10dfffffffff3823
<Warning>: Backtrace (at 4250.73):
<Warning>: void CGSUpdateManager::log() const: 0 CoreGraphics 0x00007fff986f5215 CGSBacktraceCreate + 59
<Warning>: void CGSUpdateManager::log() const: 1 CoreGraphics 0x00007fff98714688 _ZN16CGSUpdateManager14disable_updateEv + 84
<Warning>: void CGSUpdateManager::log() const: 2 AppKit 0x00007fff8e4e2de5 -[NSWindow disableScreenUpdatesUntilFlush] + 127
<Warning>: void CGSUpdateManager::log() const: 3 AppKit 0x00007fff8e4a2250 -[NSView _gainedLayerTreeHostAncestor] + 385
<Warning>: void CGSUpdateManager::log() const: 4 AppKit 0x00007fff8e4a20ae -[NSView _recursiveGainedLayerTreeHostAncestor] + 27
<Warning>: void CGSUpdateManager::log() const: 5 AppKit 0x00007fff8e4a667a -[NSScroller _recursiveGainedLayerTreeHostAncestor] + 103
<Warning>: void CGSUpdateManager::log() const: 6 AppKit 0x00007fff8e70da56 -[NSScroller _setSurfaceBacked:] + 213
<Warning>: void CGSUpdateManager::log() const: 7 AppKit 0x00007fff8e67324f -[NSScrollView setScrollerStyle:] + 304
<Warning>: void CGSUpdateManager::log() const: 8 AppKit 0x00007fff8ed0af27 +[NSScrollerImpPair _updateAllScrollerImpPairsForNewRecommendedScrollerStyle:] + 426
<Warning>: void CGSUpdateManager::log() const: 9 CoreFoundation 0x00007fff8b36fcbc __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
<Warning>: void CGSUpdateManager::log() const: 10 CoreFoundation 0x00007fff8b2611b4 _CFXNotificationPost + 3140
<Warning>: void CGSUpdateManager::log() const: 11 Foundation 0x00007fff8b5f8ea1 -[NSNotificationCenter postNotificationName:object:userInfo:] + 66
<Warning>: void CGSUpdateManager::log() const: 12 CoreFoundation 0x00007fff8b2d154c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
<Warning>: void CGSUpdateManager::log() const: 13 CoreFoundation 0x00007fff8b2c3655 __CFRunLoopDoBlocks + 341
<Warning>: void CGSUpdateManager::log() const: 14 CoreFoundation 0x00007fff8b2c2e0e __CFRunLoopRun + 910
<Warning>: void CGSUpdateManager::log() const: 15 CoreFoundation 0x00007fff8b2c2838 CFRunLoopRunSpecific + 296
<Warning>: void CGSUpdateManager::log() const: 16 HIToolbox 0x00007fff9980043f RunCurrentEventLoopInMode + 235
<Warning>: void CGSUpdateManager::log() const: 17 HIToolbox 0x00007fff998000be ReceiveNextEventCommon + 179
<Warning>: void CGSUpdateManager::log() const: 18 HIToolbox 0x00007fff997ffffb _BlockUntilNextEventMatchingListInModeWithFilter + 71
<Warning>: void CGSUpdateManager::log() const: 19 AppKit 0x00007fff8e4266d1 _DPSNextEvent + 964
<Warning>: void CGSUpdateManager::log() const: 20 AppKit 0x00007fff8e425e80 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 194
<Warning>: void CGSUpdateManager::log() const: 21 AppKit 0x00007fff8e419e23 -[NSApplication run] + 594
<Warning>: void CGSUpdateManager::log() const: 22 AppKit 0x00007fff8e4052d4 NSApplicationMain + 1832
<Warning>: void CGSUpdateManager::log() const: 23 MyApp 0x00000001000022eb main + 75
<Warning>: void CGSUpdateManager::log() const: 24 libdyld.dylib 0x00007fff97a025c9 start + 1
作为参考,我找到了根本原因,虽然我无法解释。
在 applicationDidFinishLaunching:
中,我正在初始化一个 window 控制器的共享实例,并通过调用 showWindow:nil
显示它的 window。 window 恰好包含一个 NSTableView
。此 table 视图导致其他大纲视图中的闪烁(在不相关的 window 中)。
为什么?老实说,我不知道。我从 window 中删除了所有控件,并直接从 Interface Builder 面板添加了一个空的 table 视图 → 出现问题。删除 table 视图后问题消失了。
解决方案是不要在 applicationDidFinishLaunching:
中立即打开 window。相反,我添加了一个菜单以便稍后打开它(它是一个带有调试信息的 window)。
我的解决方案是在非常小的延迟后将 window 置于前面,即:
- (void)awakeFromNib {
if (WSPreferences.currentApplication.showActivityWindow) {
//
//
[self performSelector:@selector(makeKeyAndOrderFront:) withObject:self afterDelay:0.1];
}
}