最近,我使用Apple的Quartz Debug来检测macOS中的屏幕更新。
据我所知,在NSView中,- (void)drawRect:(NSRect)dirtyRect
中的dirtyRect参数表示视图中要更新的部分。
在我新创建的项目中,我创建了一个简单的" CustomView",它的实现非常简单,如下所示:
#import "CustomView.h"
@implementation CustomView
- (void)drawRect:(NSRect)dirtyRect {
NSLog(@"dirtyRect:%@", NSStringFromRect(dirtyRect));
[[NSColor blueColor] set];
NSRectFill(dirtyRect);
}
@end
然后,我创建了一个按钮:
- (IBAction)testButtonClick:(id)sender {
[self.customView setNeedsDisplayInRect:NSMakeRect(1, 1, 50, 50)];
}
当我点击按钮时,我在控制台中有以下日志:
2017-08-07 16:11:01.914859+0800 TestScreenUpdate[17818:728751] dirtyRect:{{1, 1}, {50, 50}}
很好。 但是当我启用Quartz Debug来检测屏幕更新时,每次单击该按钮时,整个CustomView都会更新 这是gif screenshot.
Apple的DragItemAround项目没有此问题,它只更新脏部分。
我的项目由Xcode 8.3.3创建,没有任何特殊配置。
也许drawRect:
上的调用堆栈会解释一些内容:
这是我项目中drawRect:
上的调用堆栈:
#0 0x00000001000017d4 in -[CustomView drawRect:]
#1 0x00007fffa4073513 in -[NSView(NSInternal) _recursive:displayRectIgnoringOpacity:inGraphicsContext:CGContext:topView:shouldChangeFontReferenceColor:] ()
#2 0x00007fffa4072eb9 in __46-[NSView(NSLayerKitGlue) drawLayer:inContext:]_block_invoke ()
#3 0x00007fffa40729e1 in -[NSView(NSLayerKitGlue) _drawViewBackingLayer:inContext:drawingHandler:] ()
#4 0x00007fffa40723a6 in -[NSView(NSLayerKitGlue) drawLayer:inContext:] ()
#5 0x00007fffabf4c5a5 in CABackingStoreUpdate_ ()
#6 0x00007fffac06b558 in ___ZN2CA5Layer8display_Ev_block_invoke ()
#7 0x00007fffac06b070 in CA::Layer::display_() ()
这是Apple在DragItemAround项目中drawRect:
的调用堆栈:
#0 0x0000000100001007 in -[DraggableItemView drawRect:]
#1 0x00007fffa406cf99 in -[NSView _drawRect:clip:] ()
#2 0x00007fffa40bcf2f in -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] ()
#3 0x00007fffa40bd39a in -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] ()
#4 0x00007fffa40bd39a in -[NSView _recursiveDisplayAllDirtyWithLockFocus:visRect:] ()
#5 0x00007fffa406aad2 in -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] ()
#6 0x00007fffa406a2af in -[NSThemeFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:] ()
答案 0 :(得分:0)
您可能已为视图或其祖先之一启用了Core Animation图层。我认为当你更新一个图层时,窗口服务器会将整个内容看作是更新的,即使你只是重写它的一部分。
最近版本的Xcode中的Cocoa App模板默认情况下在根视图中启用图层。旧版Xcode中的模板没有,Apple的许多示例项目都是使用旧版本的Xcode创建的。
在故事板或xib中选择您的视图。然后选择查看>公用事业>显示视图效果检查器。如果为视图或其任何祖先启用了“核心动画层”,则视图将绘制到图层中。您可以尝试禁用它以查看它是否有所作为。