M P*_*M P 5 macos cocoa objective-c nsimage nsimagerep
我正在处理图像的应用程序。这就像用户最多放置 4 个图像,然后应用程序根据用户选择的模板对它们进行布局。一张图片可能会在最终视图中添加 2-3 次。
布局中的每个图像都是在 NSView 中绘制的(NSView 的 drawRect 方法使用 drawInRect 方法)。现在最终图像(通过布局所有图像的组合图像)是通过将 NSView 保存为 Image 来创建的,并且一切正常。
现在我面临的问题是一旦所有处理完成,内存就会被应用程序保留。我使用了仪器分配,我没有看到内存泄漏,但我看到“持久字节”随着应用程序的每个会话不断增加,并且一个用户报告了 GB 中的问题。请看截图。
当我在 Instruments 中进一步调查时,我在下面看到了导致内存保留的应用程序代码快照。所有都与 ImageIO 和 coreImages 相关。从仪器看下面:
然而,这似乎只是 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;
Run Code Online (Sandbox Code Playgroud)
上面的代码我用来在 NSView 的 drawRect 方法中绘制图像,图像中显示的代码用于将 NSView 获取为 Image。
更新:经过我的进一步调查,我发现它的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;
Run Code Online (Sandbox Code Playgroud)
我还尝试将kCGImageSourceShouldCache显式设置为 false(但默认情况下为 false),但结果相同。请帮助解决内存保留问题。
最后,经过大量调试,发现CGImageSourceCreateWithData是保留 NSImage 的 TIFF 数据的地方。当我改变这一行时:
CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imgData, NULL);
Run Code Online (Sandbox Code Playgroud)
和
CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)[NSURL fileURLWithPath:path], NULL);
Run Code Online (Sandbox Code Playgroud)
一切都开始正常工作,应用程序的内存使用量从 300MB(6 个图像)下降到 50-60MB,现在的行为是一致的。
除了上述更改之外,它仍然会在某处导致内存保留,因此要摆脱它,在完成所有处理后,我将每层的图像清除为“nil”,这就像魅力一样。我的印象是,将父级设置为“nil”也会发布图像,但这不起作用。
无论如何,如果有人认为drawInRect或cacheDisplayInRect有问题,请确保清除图像(如果以后不需要)。
2016 年 7 月 2 日更新
我发现kCGImageSourceShouldCache在 32 位中默认为 false,而在 64 位中默认为 true。我可以通过将以下代码设置为 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);
Run Code Online (Sandbox Code Playgroud)
希望它能帮助某人。
归档时间: |
|
查看次数: |
614 次 |
最近记录: |