macOS:setNeedsDisplayInRect引起的内存消耗

时间:2017-02-16 10:02:58

标签: objective-c macos cocoa memory-leaks

我的macOS应用程序遭受严重的内存泄漏。经过大量的调试后,我似乎找到了原因,但我仍然不太了解它。

应用程序将像素绘制到内部缓冲区,然后实际将其绘制到drawRect子类的NSView方法中的屏幕上。重绘由[self setNeedsDisplayInRect:rect]触发。

几个小时后,程序消耗了几千兆字节的RAM。然而,当我将一个循环调用setNeedsDisplayInRect来调用它时,比如,每次我想要重新绘制10,000次而不是一次时,内存消耗会在几分钟内上升到几千兆字节。

为了确保内存没有在drawRect方法中泄漏,我删除了整个正文,只留下一个空方法。

据我从文档中了解,所有存储给setNeedsDisplayInRect的rects都会被存储,直到重新编译在下一次运行事件循环中实际处理完毕。因此,当我将其调用10,000次时,我预计内存消耗会更高,但我不希望它一直保持上升 - 我希望在事件循环的一次迭代之后清除所有存储的rects。

那么,为什么在调用setNeedsDisplayInRect时内存量会继续增加?我知道每秒多次调用10,000次并不是正常使用,但是在正常情况下内存使用量也会不断增加,但速度要慢得多。

代码摘录:

- (void)drawRect:(NSRect)dirtyRect {
// Currently, nothing happening
}

// My own method, that gets called from elsewhere.
- (void) drawToScreen:(int) x : (int) y : (int)w :(int)h :(int *)data
{    
    int rectYPos = MAX(height - y - h, 0);
    NSRect rect = NSMakeRect(x, rectYPos, w, h);
    for(int i = 0; i < 10000; i++)
    {
        [self setNeedsDisplayInRect:rect];
    }
}

1 个答案:

答案 0 :(得分:1)

如果您从辅助/后台话题中调用此内容,则可能需要查看(来自Apple的文档):

&#34;如果应用程序的次级线程想要使主线程上被重绘的视图的部分,就必须这样做使用像显示,setNeedsDisplay :, setNeedsDisplayInRect :,或setViewsNeedDisplay方法:.相反,它应该向主线程发送消息或使用performSelectorOnMainThread:withObject:waitUntilDone:method来调用这些方法。&#34;

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html