【问题标题】:iphone UIImage memory leaksiphone UIImage 内存泄漏
【发布时间】:2010-12-03 18:31:25
【问题描述】:

我正在使用 UIScrollView 实现图像浏览器。由于内存成本限制,我必须实现图像动态加载(我不想使用 CATiled 图层,因为它会强制用户等待加载每个图块)。

我尝试了多种方法:

- (UIImageView*) ldPageView{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool
NSError *error;
NSData *imData = [NSData dataWithContentsOfURL:ldPageRef options:NSDataReadingUncached error:&error];
UIImage *im = [[UIImage alloc] initWithData:imData];
ldView = [[UIImageView alloc] initWithImage:im] ;
[ldView setFrame:pageRect];
[pool release];  // Release the objects in the pool.
return ldView;
}

即使是这样

- (UIImageView*) ldPageView{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool
CGDataProviderRef provider = CGDataProviderCreateWithURL ((CFURLRef)ldPageRef);
CGImageRef d = CGImageCreateWithJPEGDataProvider(provider,nil, true,kCGRenderingIntentDefault);
UIImage *im = [[UIImage alloc] initWithCGImage:d];
ldView = [[[UIImageView alloc] initWithImage:im] autorelease];
[im release];
CGDataProviderRelease(provider);
CGImageRelease(d);
[ldView setFrame:pageRect];
[pool release];  // Release the objects in the pool.
return ldView;
}

但每次我在模拟器和 iPad 上尝试时,内存都会爆炸。我已经用 Instruments 运行了我的代码,并且没有报告泄漏。 ldView 是一个 istance 变量,它与对象 dealloc 上的 ldPageRef 一起被释放(肯定会调用它)。

我也尝试将 NSURLCache sharedCache 设置为零或零,但它仍在发生。

我已阅读内存管理指南,但一切对我来说似乎都还可以。 请帮忙

【问题讨论】:

    标签: iphone uiimage nsdata


    【解决方案1】:

    尝试使用

    UIImage *im = [UIImage imageWithData:imData];
    

    而不是

    UIImage *im = [[UIImage alloc] initWithData:imData];
    

    如果可能,请始终避免分配,否则您必须确保手动释放对象。

    【讨论】:

    • 至少问题与我将 UIViewController 中的视图添加到父级的事实有关,然后当内存不足时我关闭了该控制器,但没有从父级删除视图。所以它仍然保持在retain count = 1。奇怪的是,连Analyzer都没有找到它。
    【解决方案2】:

    这很可能是您创建 UIImage 的方式。尝试这样创建您的图像..

    [UIImage imageWithData:imData];
    

    而不是

    [[UIImage alloc] initWithData:imData];  
    

    这将返回一个自动释放的对象(它是一个类方法),因此您以后不必尝试自己释放它。

    【讨论】:

    • 我已经这样改变了我的代码: NSError *error; NSData *imData = [NSData dataWithContentsOfURL:ldPageRef options:NSDataReadingUncached error:&error]; UIImage *im = [UIImage imageWithData:imData]; ldView = [[[UIImageView alloc] initWithImage:im]autorelease] ; [ldView setFrame:pageRect];但它又发生了。我错过了什么?
    • 在释放池对象之前是否添加了对 [pool drain] 的调用?另外,您的代码中的 ldView 是什么?它是属性还是 iVar?
    【解决方案3】:

    你永远不会释放你分配的对象。你需要改变:

    [[UIImage alloc] initWithData:imData];
    [[[UIImageView alloc] initWithImage:im];
    

    到:

    [[[UIImage alloc] initWithData:imData] autorelease];
    [[[UIImageView alloc] initWithImage:im] autorelease] ;
    

    【讨论】:

    • 我已经这样改变了我的代码: NSError *error; NSData *imData = [NSData dataWithContentsOfURL:ldPageRef options:NSDataReadingUncached error:&error]; UIImage *im = [UIImage imageWithData:imData]; ldView = [[[UIImageView alloc] initWithImage:im]autorelease] ; [ldView setFrame:pageRect];但它又发生了。我错过了什么?
    • 在释放之前,您是否已经排干了池 - [池排水]?
    • 释放池也会释放它跟踪的所有对象。
    【解决方案4】:

    确实我在 UIImageView 中发现了内存泄漏。只是你从来不去理会它,因为你可能一直从 App 包中打开图片,而这些图片正在被 iOS 缓存。

    但是,如果您从网络下载大量图像(例如 40 张 iPhone 相机照片),将它们保存到文档中并在子视图控制器中一遍又一遍地打开它们,就会出现内存泄漏。你不需要有 40 张不同的图片,一次又一次地加载一张图片就足够了。

    您的测试应用已禁用 ARC,并且每次推送控制器时,都会从文件加载图像并显示在子视图控制器中。

    在您的子视图控制器中,您将创建一个 UIImageView 并将 UIImage 对象分配给图像视图的 .image 属性。当您离开子视图控制器时,您会正确释放图像视图。在 iPhone 4s 上,您的应用打开的图片不会超过 80 张。我的崩溃了大约 70 张图片(使用 iOS 6.1)。并在崩溃前查看仪器应用程序。内存已满是 CFMalloc 块。

    我找到的解决方案很简单:在释放图像视图之前将图像属性设置为 nil。再次,查看仪器应用程序。现在看起来就像您所期望的那样,您的应用不再崩溃。

    我认为同样的泄漏适用于 UIWebView 用于显示图像的任何内容,而 Apple 对此一无所知。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-23
      相关资源
      最近更新 更多