7

我的应用程序由于在应用程序使用过程中的某个时间点出现内存压力而终止,我已将问题隔离为导致问题的一大块代码。

我将复制下面的代码块,但首先我将描述它在做什么。

说明

我有一个遍历视频列表的 for 循环。对于每个视频,for 循环会增加包含滚动视图的大小,绘制一个标签和一个按钮(两者都与视频有关),并异步抓取视频的缩略图并将其放在按钮下方。

问题

抓取缩略图部分是问题所在。我不认为这是异步完成的事实是问题,因为我已经同步尝试过并且终止仍然发生。当我注释掉抓取缩略图的代码(下面代码中的整个异步部分)时,应用程序不会崩溃。

代码

注意:为了简洁起见,我在某些情况下使用注释来替换代码。

for (int i = [_videoURLs count]-1; i >= 0 ; i--)
    {
        //increase the scrollview size

        //get background image:
        dispatch_async(screenshotQueue, ^{

            AVURLAsset *as = [[AVURLAsset alloc] initWithURL:currentURL options:nil];
            AVAssetImageGenerator *ima = [[AVAssetImageGenerator alloc] initWithAsset:as];
            ima.appliesPreferredTrackTransform = YES;
            NSError *err = NULL;
            CMTime time = CMTimeMake(1, 24);
            CGImageRef imgRef = [ima copyCGImageAtTime:time actualTime:NULL error:&err];
            UIImage *thumbnail = [[UIImage alloc] initWithCGImage:imgRef];

            dispatch_async(dispatch_get_main_queue(), ^{

                UIImageView *backgroundImage = [[UIImageView alloc]initWithFrame:buttonFrame];
                backgroundImage.image = thumbnail;
                backgroundImage.layer.opacity = 0;
                [self.videoScrollView addSubview:backgroundImage];

                [self.videoScrollView sendSubviewToBack:backgroundImage];

                [UIView animateWithDuration:0.5 delay:0.0 options: UIViewAnimationOptionCurveEaseInOut
                 animations:^{
                     backgroundImage.layer.opacity = 1;
                 }
                 completion:^(BOOL finished){}];

            });

        });

        //add title to the screen caps

        //draw the button

    }

我正在使用 Xcode 5,在装有 iOS 7 的新设备上进行测试。我是自学成才的,所以我确信我已经养成了相当多的坏习惯,但我希望我错过了一些明显的东西有更多经验的人会接受。

我已经尝试了相当多的谷歌搜索和堆栈溢出搜索,并尝试查看诊断、日志和内存配置文件以进一步隔离问题,但无济于事。

任何帮助将不胜感激!

编辑

如何重现错误:

  1. 转到视频列表
  2. 离开视频列表
  3. 重复 1+2 4 或 5 次导致崩溃

步骤 2. 简单地从其父视图中删除整个滚动视图,然后重绘它。我知道每次返回视频列表时都没有必要重新绘制视频列表,但我这样做是出于某种原因,我不认为这是问题的根源(我可能是错的)。

编辑 2

这是内存配置文件的图像: 在此处输入图像描述

4

2 回答 2

13

您显示的代码有很大的泄漏。您正在创建一个核心基础对象:

CGImageRef imgRef = [ima copyCGImageAtTime:time actualTime:NULL error:&err];

但我没有看到相应CFRelease的 .

你的代码应该是:

CGImageRef imgRef = [ima copyCGImageAtTime:time actualTime:NULL error:&err];
UIImage *thumbnail = [[UIImage alloc] initWithCGImage:imgRef];
CFRelease(imgRef);
于 2013-11-01T13:33:51.120 回答
2

好吧,所以我找到了一个不错的解决方案。我仍然不完全确定为什么这是一个问题,但我有一些怀疑。

我相信生成缩略图的过程过于密集,无法通过 for 循环在线程上重复执行。我有这种预感,所以决定调整上面的代码。我不会每次都生成新的缩略图,而是将新生成的屏幕截图以 png 格式保存到文档主目录中。然后下一次,我会从那里加载这个资源。这导致内存问题消失。

我希望这对有类似问题的人有所帮助-如果有人要添加任何内容或有更好的答案,我会全力以赴。

于 2013-11-01T13:21:44.147 回答