macOS 10.13 High Sierra:后台线程上的[NSGraphicsContext flushGraphics]无效

时间:2017-09-26 19:01:49

标签: multithreading user-interface cocoa appkit macos-high-sierra

直到macOS 10.12,以下代码在后台线程上正常工作:

[nsView lockFocusFocus];
... draw something ...
[[NSGraphicsContext currentContext] flushGraphics];
[nsView unlockFocus];

然而,使用10.13,flushGraphics不再立即更新视图的内容。

我知道现在不鼓励从后台线程中绘图,但这并不意味着它不再可能。事实上,所有东西......都画了一些东西......仍然是视图的后盾商店。下次在主UI线程上调用drawRect:时,将刷新视图并正确放置所有内容。

如何立即实现?有没有办法让视图立即可见?

2 个答案:

答案 0 :(得分:0)

事实证明,对于macOS 10.13,如果 drawRect:实际上并未在该方法的范围内绘制任何内容,则即使修改了其后备存储,视图的显示也不会刷新。 / p>

因此,如果你想将未决的更改刷新到屏幕,那么诀窍是通过绘制至少一个不可见的小矩形来使AppKit 认为绘制了一些内容:

- (void) drawRect: (NSRect)rect
{
    if (drawRectWasRequestedByRefresh) {
       // flush pending changes drawn on background thread
       [[NSColor clearColor] set];
       [NSBezierPath strokeRect: NSMakeRect(0,0,1,1)];
       drawRectWasRequestedByRefresh = NO;
    } else {
       // draw your view's regular contents here
    }
}

要从后台线程触发刷新,请使用此hack:

- (void) refresh
{
    drawRectWasRequestedByRefresh = YES;
    [self setNeedsDisplay: YES];
}

这肯定是一个肮脏的黑客,只有需要立即从后台线程绘图的应用程序才需要(无论出于何种原因)。如果有人知道更好的解决方案,我会很高兴听到它!

答案 1 :(得分:0)

看来最近对High Sierra的macOS更新,可能是10.13.4,这个问题已经消失了。因此,flushGraphics现在会像以前一样将更改刷新到屏幕上。