【问题标题】:Memory Leak when create a UIImage创建 UIImage 时内存泄漏
【发布时间】:2013-07-17 05:28:26
【问题描述】:

我有以下方法在文档目录中获取一个 pdf 文件并从中创建一个缩略图。如 cmets 所示,此方法在两个地方泄漏内存。由于我使用的是 ARC,我不确定它为什么会泄漏内存。我该如何解决这个问题。

  + (UIImage*)createPdfThumbnail:(NSString*)pdfFilePath {


        NSURL *targetURL = [NSURL fileURLWithPath:pdfFilePath];
        CGPDFDocumentRef pdf = CGPDFDocumentCreateWithURL((__bridge CFURLRef)targetURL);  // 3.0% of memory leak

        CGPDFPageRef page = CGPDFDocumentGetPage(pdf, 1);//for the first  page
        CGRect aRect = CGPDFPageGetBoxRect(page, kCGPDFCropBox);
        UIGraphicsBeginImageContext(aRect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();

        CGContextSaveGState(context);
        CGContextTranslateCTM(context, 0.0, aRect.size.height);
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextTranslateCTM(context, -(aRect.origin.x), -(aRect.origin.y));

        CGContextSetGrayFillColor(context, 1.0, 1.0);
        CGContextFillRect(context, aRect);

        CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, aRect, 0, false);
        CGContextConcatCTM(context, pdfTransform);
        CGContextDrawPDFPage(context, page);

        UIImage *thumbnail = UIGraphicsGetImageFromCurrentImageContext(); // 97% of memory leak
        CGContextRestoreGState(context);
        UIGraphicsEndImageContext();
        CGPDFDocumentRelease(pdf);
        return thumbnail;

}

编辑

-(void)fromJSON:(NSDictionary *)JSON{
    [super fromJSON:JSON];
    self.path = JSON[@"path"];
    //Create and save thumbnail
    if (self.parentSpecSheet != nil){
        @autoreleasepool {
            UIImage* thumbnail = [Utilities createPdfThumbnail:self.path];
            Photo* thumbnailPhoto = [Photo addObject];
            [thumbnailPhoto setDelta:@(0)];
            [thumbnailPhoto setImage:thumbnail];
            [thumbnailPhoto.file setDelta:@(0)];
            self.parentSpecSheet.thumbnail = thumbnailPhoto;
        }
    }
}

【问题讨论】:

标签: ios memory-leaks uiimage


【解决方案1】:

两个想法:

  1. 当我在 iOS5 中测试您的代码时,我遇到了来自 CGContextDrawPDFPage 的重大泄漏(如果您搜索 "CGContextDrawPDFPage leak",您会看到大量关于此问题排列的引用)。这似乎是一个已知问题。

    不过,我从上面的代码中发现 iOS 6 中没有明显的泄漏。

  2. 如果您在 iOS 6 中仍然看到此泄漏,那么我怀疑问题不在于上述代码。您是否报告了任何其他泄漏?我还建议您确认拥有此thumbnail 的对象本身已成功释放(例如,其dealloc 方法中的日志/断点)。

    不幸的是,当您查看泄漏工具时,它报告的是泄漏对象的实例化位置,而不是泄漏发生的位置。您可能想确认此thumbnail 的所有者是否以某种方式保持对它的强引用(例如,所有者本身具有保留周期或类似的东西)。

【讨论】:

  • 嗨 Rob,感谢您的帮助,我在 iOS 5.1 中运行它,我添加了调用此方法的代码。我在后台线程中运行这两个函数
  • @ila 我认为这是 iOS 5 的错误,因为已在 iOS 6 中修复。请参阅 stackoverflow.com/questions/14141423/… 了解可能适用于 iOS 5 的一些潜在解决方法(尽管我无法证明它们)。对我来说,问题是考虑到 iOS 6 的高转换率(我可能仍倾向于支持 iOS 5 目标,但可能会在运行时 iOS 版本检查中不生成运行 iOS 6.0 之前版本的设备的自定义缩略图)。只是在旧 iOS 版本中投入多少时间来解决错误的问题。
  • 即使在 i0S 6 中它也会泄漏内存。
  • @ila 当我运行这段代码时,我看到 6.0 和更高版本的分配适度增加(但在 5.0 中存在大量泄漏)。我有点惊讶你没有看到 b/w 5.x 行为和 6.x 的差异。这对我来说意义重大。无论如何,如果您真的从 Leaks 工具的UIGraphicsGetImageFromCurrentImageContext 行收到泄露的消息,这意味着图像本身正在泄漏。因此,此代码不是泄漏的原因,而是泄漏只是让您知道泄漏对象的创建位置。有关其他建议,请参阅我原始答案的第二点。
猜你喜欢
  • 1970-01-01
  • 2013-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 1970-01-01
相关资源
最近更新 更多