2010-12-03 129 views
2

我正在实现一个图像浏览器,使用UIScrollView。由于内存costranints,我必须实现图像动态加载(我不想使用CATiled层,因为它迫使用户继续等待加载每个瓷砖)。iphone UIImage内存泄漏

我试着用不同的方式轿跑车:

- (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上,内存爆炸。我用仪器运行了我的代码,并且没有泄漏报告。 ldView是一个istance变量,通过ldPageRef对象dealloc(肯定会调用它)释放它。

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

我读过内存管理指南,但everythimg对我来说似乎没问题。 请帮很可能

+1

尝试[pool drain] – Vjy 2010-12-03 18:44:17

回答

2

尝试使用

UIImage *im = [UIImage imageWithData:imData]; 

而不是

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

始终避免allocs如果可能的话,否则你必须确保你手动释放的对象。

+0

至少这个问题与我将UIViewController中的视图添加到父项的事实有关,然后当内存很低时,我忽略了该控制器,但没有从父项中移除视图。所以仍然保留计数= 1。奇怪的是,即使分析仪也没有找到它。 – Aletheia 2010-12-19 08:36:03

2

更多的是你如何创造你的UIImage。尝试创建映像,作为这样..

[UIImage imageWithData:imData]; 

,而不是

[[UIImage alloc] initWithData:imData]; 

这将返回一个自动释放的对象(这是一个类的方法),这样你就不必尝试自己后释放。

+0

我改变了我的代码: 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]; 但它再次发生。我错过了什么? – Aletheia 2010-12-04 01:49:15

+0

您在释放池对象之前是否已将呼叫添加到[pool drain]?另外,你的代码中的ldView是什么?它是一个财产还是一个iVar? – DerekH 2010-12-06 16:51:04

1

你永远不会释放你的alloc'd对象。您需要更改:

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

到:

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

事实上,我已经找到的UIImageView内存泄漏。你从不关注它,因为你可以随时从App包打开图片,这些图片被iOS缓存。

但是如果你从网络上下载了许多图片(比如40 iPhone摄像头的照片),将它们保存到文件和子视图控制器一遍遍打开它们,内存泄漏适用。您不需要有40个不同的图像,它足以一次加载一个图像。

您的测试应用程序禁用了ARC,并且图像正在从文件加载并显示在子视图控制器中,每次该控制器被推入时。

在你的子视图控制器,你将创建一个的UIImageView并指定UIImage对象的图像视图的财产图像配。当您离开子视图控制器时,您可以正确释放图像视图。在iPhone 4s上,您的应用不会打开超过80张图像。我的图像崩溃了大约70(与iOS 6.1)。在崩溃之前查看一下该仪器的应用程序。内存中充满了CFMalloc块。

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

我认为相同的泄漏适用于UIWebView用来显示图像和苹果不知道它。