2016-02-26 56 views
3

我正在使用过程映像的应用程序。这就像用户在最多4张图片上下载并根据用户选择的模板布局它们。最终视图中可能会添加一个图像2-3次。保留NSImage drawInRect和NSView cacheDisplayInRect内存

布局中的每个图像都在NSView中绘制(使用drawInRect方法的NSView的drawRect方法)。现在通过将NSView保存为Image来创建最终图像(通过布置所有图像的组合图像),并且一切运行良好。

现在我面临的问题是内存被所有处理完成后应用程序保留。我使用过仪器分配,并且没有看到内存泄漏,但是我看到“持续字节数”随着每次应用程序会议和一个用户报告的问题持续增加。请看截图。

Instruments memory usage ImageIO_TIFF 当我在仪器进一步调查,我看到下面的应用程序代码的捕捉是导致内存保留期限。所有都与ImageIO和coreImages相关。从仪器见下图:

Instruments code snap

然而,这似乎是唯一的问题,10.10及以上系统。在10.9.x中测试了相同版本的应用程序,内存使用率仍保持在60MB。在应用会话执行过程中,它会达到200MB,但一旦完成,它会回到50-60MB,通常适用于各种应用。

[_photoImage drawInRect: self.bounds fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0 respectFlipped: YES hints: nil]; 
      _photoImage = nil; 

上面,我是用绘制图像在图像中显示的NSView的drawRect方法和代码的代码被用于获取的NSView为图像。

更新:后,我进一步调查,我发现它的CGImageSourceCreateWithData被缓存NSImage中的TIFF数据。更多有史以来我使用下面的代码来裁剪图像,如果我取消注释它内存消耗正常工作。

NSData *imgData = [imageToCrop TIFFRepresentation]; 
CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imgData, NULL); 
CGImageRef maskRef = CGImageSourceCreateImageAtIndex(source, 0, NULL); 
CGImageRef imageRef = CGImageCreateWithImageInRect(maskRef, rect); 
NSImage *cropped = [[NSImage alloc] initWithCGImage: imageRef size:rect.size]; 

CGImageRelease(maskRef); 
CGImageRelease(imageRef); 
CFRelease(source); 
//CFRelease(options); 
imgData = nil; 

我也试图明确设置kCGImageSourceShouldCache假(但它默认为false),但相同的结果。 请帮助解决内存保留问题。

+0

看起来我已经问过一些很容易理解或很难回答的问题。 :(请帮助,我真的卡住了。 –

回答

0

最后经过大量调试后发现,CGImageSourceCreateWithData是保存NSImage的TIFF数据的地方。当我改变了这一行:

CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imgData, NULL); 

CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], NULL); 

一切刚刚开始工作的罚款和应用程序的内存使用量下降了300MB,从(为6个图像)到50-60MB,它现在是一致的行为。

除了以上改变,它仍然引起记忆保持的地方,从而摆脱的是,所有的处理完成后,我清除每一层的图像“零”和作品般的魅力。我的印象是让父母成为'无'也会发布图片,但那不起作用。

无论如何,如果任何人似乎与drawInRect或cacheDisplayInRect问题,然后确保清除图像,如果不需要稍后。

更新2016年7月2日

我发现kCGImageSourceShouldCache默认情况下在32位虚实64位。通过将它设置为false,我能够通过下面的代码释放内存。

const void *keys[] = { kCGImageSourceShouldCache}; 
    const void *values[] = { kCFBooleanFalse}; 
    CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL); 

    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)[image TIFFRepresentation], optionsDictionary); 

希望它有助于某人。