【问题标题】:macOS 10.13 High Sierra: [NSGraphicsContext flushGraphics] on background thread has no effectmacOS 10.13 High Sierra:后台线程上的 [NSGraphicsContext flushGraphics] 无效
【发布时间】:2018-04-23 18:38:36
【问题描述】:

在 macOS 10.12 之前,以下代码在后台线程上运行良好:

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

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

我知道现在不鼓励从后台线程进行绘图,但这并不意味着它不再可能。事实上,...中的所有内容...绘制一些东西...仍然进入视图的后备存储。一旦 drawRect: 下一次在主 UI 线程上被调用,视图就会刷新,所有内容都正确到位。

如何让这立即发生?有没有办法让视图的更改立即可见?

【问题讨论】:

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


    【解决方案1】:

    事实证明,在 macOS 10.13 中,如果 drawRect: 实际上没有在该方法的范围内绘制任何内容,那么即使修改了其后备存储,视图的显示也不会刷新。

    因此,如果您想将待处理的更改刷新到屏幕,诀窍是让 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
        }
    }
    

    要从后台线程触发刷新,请使用以下技巧:

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

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

    【讨论】:

      【解决方案2】:

      随着最近对 High Sierra 的 macOS 更新(可能是 10.13.4),此问题似乎已经消失。因此,flushGraphics 现在确实像以前一样将更改刷新到屏幕。

      【讨论】:

        猜你喜欢
        • 2018-03-06
        • 1970-01-01
        • 1970-01-01
        • 2018-04-03
        • 2018-03-14
        • 1970-01-01
        • 2018-03-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多