Ios 图像IO内存不断增长

Ios 图像IO内存不断增长,ios,uiimage,instruments,Ios,Uiimage,Instruments,我在装有虚拟机跟踪器的Instruments中运行我的应用程序,发现图像IO内存消耗不断增加 实际上,该应用程序使用initWithContentsOfFile:从磁盘读取了大量图像。我曾经读过一篇文章,说这个方法是撒旦的产物,所以我用下面的方法代替了它: NSData *data = [NSData dataWithContentsOfFile:path]; UIImage *image = [UIImage imageWithData:data]; 这大大减少了虚拟内存(约60%),如下

我在装有虚拟机跟踪器的Instruments中运行我的应用程序,发现图像IO内存消耗不断增加

实际上,该应用程序使用
initWithContentsOfFile:
从磁盘读取了大量图像。我曾经读过一篇文章,说这个方法是撒旦的产物,所以我用下面的方法代替了它:

NSData *data = [NSData dataWithContentsOfFile:path];
UIImage *image = [UIImage imageWithData:data];
这大大减少了虚拟内存(约60%),如下所示:

但是,为什么图像IO虚拟内存会随着时间的推移不断增长,而我的应用程序只使用了15MB的实时内存

我可以做些什么来确保释放此图像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 DATA WITH CONTENTS OFFILE:path options:NSDATAREADINGUCACHED error:nil]
  • Move
    UIImage*image=[UIImage-imageWithData:data]到主队列
  • 在主队列上执行所有操作

这让我觉得问题可能在别处。

您至少应该将后台处理打包到自动释放池中:

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;
        });
    }
});
通过这种方式,您可以确保背景线程上的所有自动释放对象尽快消失。

多亏了我发现图像被
NSCache
保留

问题是
NSCache
没有释放任何内存对象警告。解决方案:让它观察
UIApplicationIDReceiveMemoryWarningNotification
,并在发生这种情况时删除其所有对象。这就是仪器现在的样子:

乐器太棒了。感谢@NikolaiRuhe和@nielsbot让我挖得更深


另外,我应该补充一点,使用
NSData
时内存消耗会降低,因为
dataWithContentsOfFile
不考虑视网膜文件(d'uh)。所以
imageWithContentsOfFile:
可能仍然是撒旦的后代,但这并不是撒旦的错

在Allocations instrument中,您可以打开分配事件调用堆栈的所有记录。也许你有一个额外的意外保留sonewhere?@nielsbot如果有,活动内存会比虚拟内存高很多吗?这就是说,我已经检查了仪器和静态分析仪中是否存在泄漏。我想我主要对分配的来源感到好奇。@nielsbot给你:)好吧——看起来有很多CFData对象。。。如果单击CFData旁边的“显示详细信息”箭头,然后浏览实例,查看每个分配事件记录的调用堆栈,以查看分配的原因。这难道不是不必要的吗?知道
数据可以在
imageWithData:
之后释放,并且
图像可以在第二次
调度\u async
结束时释放,这难道还不够聪明吗?@hpique否。如果启用了优化,并且调用方和调用方都进行了优化,ARC有时可能会避免将对象放入自动释放池被调用方是使用ARC编译的,但您不能依赖它。此处
dataWithContentsOfFile:
创建一个自动删除的对象,如果添加池,该对象会消失得更快。您也可以尝试将
NSDataReadingMappedaways
传递到
dataWithContentsOfURL:options:错误: