我需要重绘部分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,它可以在没有所有这些hackery的情况下工作:
-(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
答案 0 :(得分:2)
是什么让你如此确定这是不良行为?我在Quartz Debugger下看到的行为表明,当我点击Update按钮时,点击按钮的矩形与传递的dirtyRect的矩形的交集会闪烁。这是预期的,因为系统在runloop(鼠标向上)的同一通道内合并所有需要的绘图以提高效率。
你的其他hacky方法绕过了这种行为,因为按钮的状态是在一个(实际上是两个:鼠标按下和鼠标按下)传递中处理的,你的视图更新是在后续传递中处理的。如果您密切注意延迟绘图点击中的更新闪烁(按钮闪烁,再次打开,然后视图的脏区闪烁),则会进行验证。点击视图本身不涉及任何其他东西(从技术上来说,它是非不透明的祖先),所以所有视图的脏集合的结合仅限于你请求的矩形。
我希望这会有所帮助。