2014-01-21 23 views
0

所以我有一些代码在NSThread中运行,在循环中创建了一大堆NSImage s。每个图像的一小部分被绘制到另一个NSImage,然后该线程退出。drawInRect保留NSImage直到将来的某个点?

所以,像

NSImage *outputImage = [[NSImage alloc] initWithSize:size]; 
[outputImage lockFocus]; 
while(1000 times) 
    NSImage* image = [[NSImage alloc] initWithSize:size]; 
    ... image is processed ... 
    [image drawInRect: ... fromRect: ... ] 
[outputImage unlockFocus]; 

一旦完成,该线程使用performSelectorOnMainThread到NSImage中创建发送回主线程将它放置在一个视图。

这一切工作正常,最终的形象是完全如我所料。但是,在循环过程中,应用程序的内存使用量会线性上升 - 就好像每个NSImage直到稍后才会释放。我的理论是,drawInRect调用正在某处进行流水线调用,直到后来才实际执行。它是否正确?如果是这样,我该如何预防它?如果我现在让我的循环计数器过大,我的应用程序将崩溃,我想避免这种情况。

我试着将锁定和解锁的焦点放入循环中,但这没有什么区别。

我已经证实,如果我只拿出drawInRect调用,内存使用率(或多或少)在线程的整个生命周期内是平坦的。只有当我打电话时,记忆力才会上升。

我(明显?)在这个项目中使用ARC,它在OSX10.9中运行。

回答

2

这听起来像你的NSImages在某些时候被添加到autorelease池。直到游泳池排水后,他们通常不会被冲洗。

在情况下,这样的你想使自己的自动释放池:

NSImage *outputImage = [[NSImage alloc] initWithSize:size]; 
[outputImage lockFocus]; 
while(1000 times) { 
    @autoreleasepool { 
     NSImage* image = [[NSImage alloc] initWithSize:size]; 
     ... image is processed ... 
     [image drawInRect: ... fromRect: ... ] 
    } 
} 
[outputImage unlockFocus]; 

这将创建一个子池,将获得每通排水,所以你不会有一个巨大的积聚图片。

+0

非常感谢 - 可能就是这样。我感兴趣,但我认为自动引用计数操作很像使用boost :: shared_pointers无处不在(我来自C++背景)。所以,一旦某些事情超出了范围,或者被分配了空值,它就会被释放。我从你的评论中认为ARC不是这种情况,我必须明确地声明特殊块来实现这一点。 –

+0

我相信有些情况下你可以完全避免自动释放,但我不确定你的代码在这种情况下触发了什么,如果它实际上是什么让你伤心。 –

+0

昨晚我尝试了这个修复方法,它彻底清除了这个问题。不调用drawInRect也可以避免这个问题 - 当然它也会阻止代码做任何事情。当我看起来可能需要它时,我只需要记住使用@autorelease。谢谢你的帮助。 –