4

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

带有 initWithContentsOfFile 的仪器:

实际上,该应用程序使用initWithContentsOfFile:. 我曾经读到这种方法是撒旦的产物,所以我将其替换为以下内容:

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

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

带有 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];到主队列
  • 在主队列上做所有事情

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

4

2 回答 2

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;
        });
    }
});

这样,您可以确保后台线程上的任何自动释放对象尽快消失。

于 2013-08-16T10:26:52.653 回答
1

感谢Heapshot Analysis,我发现图像被NSCache.

问题是NSCache在内存警告中没有释放任何对象。解决方案:让它观察UIApplicationDidReceiveMemoryWarningNotification并在发生这种情况时移除所有对象。这是 Instruments 现在的样子:

带有内存警告耗尽的仪器

乐器真棒。感谢@NikolaiRuhe 和@nielsbot 让我深入挖掘。

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

于 2013-08-16T10:32:49.370 回答