我使用VM Tracker在Instruments中运行我的应用程序,发现了不断增长的Image IO内存消耗。
实际上,该应用程序通过initWithContentsOfFile:
从磁盘读取了相当多的图像。我曾经读过这个方法是撒旦的产物,所以我用以下代替它:
NSData *data = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage imageWithData:data];
这大大减少了虚拟内存(约60%),如下所示:
但是,为什么Image IO虚拟内存会随着时间的推移不断增长,当没有任何泄漏且我的应用程序只使用15MB的实时内存时?
我可以采取哪些措施来确保释放此Image IO内存吗?
基本上,从磁盘读取的图像是这样完成的:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^(void) {
NSData *data = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
imageView.image = image;
});
});
我还尝试了以下内容而没有任何重大变化:
[NSData dataWithContentsOfFile:path options:NSDataReadingUncached error:nil]
代替UIImage *image = [UIImage imageWithData:data];
移至主队列这让我觉得问题可能出在其他地方。
答案 0 :(得分:2)
您至少应该将后台处理包装到自动释放池中:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^(void) {
@autoreleasepool {
NSData *data = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
imageView.image = image;
});
}
});
这样可以确保后台线程上的任何自动释放的对象尽可能快地消失。
答案 1 :(得分:1)
感谢Heapshot Analysis我发现图片是由NSCache
保留的。
问题是NSCache
没有在内存警告上释放任何对象。解决方案:让它观察UIApplicationDidReceiveMemoryWarningNotification
并在发生这种情况时删除所有对象。这就是仪器现在的样子:
仪器很棒。感谢@NikolaiRuhe和@nielsbot让我深入挖掘。
另外,我应该补充一点,使用NSData
时内存消耗会降低,因为dataWithContentsOfFile
不会影响视网膜文件(呃)。所以imageWithContentsOfFile:
可能仍然是撒旦的产卵,但这不是它的错。