我需要重绘一些NSView的一部分。
- (IBAction)onUpdateView:(id)sender
{
NSRect updatedRect = ... // Redraw updated area only.
[self.view setNeedsDisplayInRect:updatedRect];
}
当我使用这个简单明了的解决方案时,Quartz Debug 会突出显示更大区域的重绘 - 直到视图的整个区域。
我注意到,如果 [NSView setNeedsDisplayInRect] 的调用被推迟到下一个运行循环周期,或者我只是执行 [runloop runUntilDate:+0],问题就会消失:
- (IBAction)onUpdate:(id)sender
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self setNeedsDisplayInRect:updatedRect];
});
}
或
- (IBAction)onUpdateAndRunLoop:(id)sender
{
[self.view setNeedsDisplayInRect:updatedRect];
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.0]]; // EEW
}
但是如果在mouseDown处理程序中调用setNeedsDisplayInRect,它可以在没有所有这些黑客的情况下工作:
-(void)mouseUp:(NSEvent*)event
{
NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil];
int size = 100;
[self setNeedsDisplayInRect:NSMakeRect(p.x-size/2, p.y-size/2, size, size)];
}
这是怎么回事,该怎么办?
此问题的隔离 Xcode 项目在这里:http://beta.kalinsky.ru/wtf/testRedraw.tar.gz
是什么让你如此确定这是不良行为?我在 Quartz 调试器下看到的行为表明,当我点击"更新"按钮时,单击按钮的矩形与传递的 dirtyRect 的矩形的交点会闪烁。这是意料之中的,因为系统将所有需要的绘图合并到运行循环的同一通道(鼠标向上)以提高效率。
您的其他黑客方法会绕过此行为,因为按钮的状态在一次(实际上是两次:鼠标按下和鼠标向上)中处理,而视图的更新在后续传递中处理。如果您密切关注延迟绘图单击中的更新闪烁(按钮向下闪烁,再次向上闪烁,然后视图的脏区闪烁),则会验证这一点。对视图本身的点击不涉及其他内容(好吧,从技术上讲,它是不透明的祖先),因此所有视图的脏矩形的联合仅限于您请求的矩形。
我希望这有所帮助。