图像IO内存不断增长

时间:2013-08-15 15:31:45

标签: ios uiimage instruments

我使用VM Tracker在Instruments中运行我的应用程序,发现了不断增长的Image IO内存消耗。

Instruments with initWithContentsOfFile:

实际上,该应用程序通过initWithContentsOfFile:从磁盘读取了相当多的图像。我曾经读过这个方法是撒旦的产物,所以我用以下代替它:

NSData *data = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage imageWithData:data];

这大大减少了虚拟内存(约60%),如下所示:

Instruments with imageWithData:

但是,为什么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];移至主队列
  • 在主队列上执行所有操作

这让我觉得问题可能出在其他地方。

2 个答案:

答案 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并在发生这种情况时删除所有对象。这就是仪器现在的样子:

Instruments with memory warning draining

仪器很棒。感谢@NikolaiRuhe和@nielsbot让我深入挖掘。

另外,我应该补充一点,使用NSData时内存消耗会降低,因为dataWithContentsOfFile不会影响视网膜文件(呃)。所以imageWithContentsOfFile:可能仍然是撒旦的产卵,但这不是它的错。