UIImageView得到了奇怪的保留计数,我需要释放它两次以避免泄漏

时间:2011-05-13 01:51:10

标签: iphone objective-c ios ipad ios4

我有一个我在nib文件中设置的UIImageView。我从互联网上下载图像并将图像设置为UIImageView。当我发布它时保留计数2?如果我只使用1个版本,它将不会显示任何内存泄漏,但我可以在“仪器分配”中看到它永远不会被释放。当我像下面两次发布UIImageView时,它运行良好。但是我永远不应该发布它两次?!?!

标题中的

IBOutlet UIImageView *background;
<。>在.m中加载图片:

 /* Load Image code */
 id path = [NSString stringWithFormat:@"http://www.image.com/aImage.jpg"];
 NSURL *url = [NSURL URLWithString:path];
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 NSData* urlData = [[NSData alloc] initWithContentsOfURL:url];
 [background setImage:[UIImage imageWithData:urlData]];
 [urlData release];
 [pool release];

在dealloc函数中:

- (void)dealloc {
    NSLog(@"Backgroud count: %i",[background retainCount]); // Prints 2
    [background release];
    [background release]; // Does not "leak" if i have 2x release
    [super dealloc];
}

这是使用UIImageView背景的唯一代码。

编辑:

我忘了提到的是我在这样的for循环中运行这段代码。但这个for循环只执行一次!但这没关系?

for (id theKey in dictionary) {
     /* Load Image code above is here */
}

2 个答案:

答案 0 :(得分:3)

我相信我已经弄清楚了问题是什么。 Apple建议您通过IBOutlet保留连接的对象(在本例中为图像视图)。你说你还没有这样做,但你应该遵循Apple的建议。你应该在iphonedevsdk.com forum post中概述你应该解决这个问题的原因,该问题链接到一个全神贯注的大书呆子牧场blog post

在iOS上,nib加载机制使用setter,如果你的插座有一个,但如果没有,它使用键值编码;具体来说,它使用setValue:forKey:保留值(这是记录在案的,但有点意外)。作为视图控制器顶视图子视图的图像视图由该视图保留。它也由此键值设置程序保留。因此,您不知道,您的对象有两个对图像视图的引用。 Apple提出了保留属性建议,以便您了解视图是否被保留。

你仍然不应该担心保留计数,但你应该做以下两件事之一:将此IBOutlet保留为保留属性并在中释放 {{ 1}}和viewDidUnload(虽然每次只有一次!),或遵循BNR的建议并明确指定属性:

dealloc

在这种情况下,您无需自行发布。在这两种情况下,请确保@property (assign, nonatomic) IBOutlet UIImageView *background; 属性访问者。


此前:

Don't look at retain count,如果没有检测到泄漏,那么不要担心。 UIKit框架可能会因您不知情的原因而保留该视图。

此外,如果@synthesize不是保留属性:

background

并且你在xib中创建它,你不应该发布 at all ,因为你不拥有它。也就是说,你不是responsible for its memory;为您提供责任的操作包括:在对象上调用@property (retain) IBOutlet UIImageView *background; ,或使用名称以retainalloccopy或{{开头的方法创建对象1}}。

答案 1 :(得分:0)

我对nib文件了解不多,我曾经按照下面的说法进行操作

  background=[[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)];
  //Now the reatin count is 1
 [background setImage:[UIImage imageWithData:urlData]];
  [someView addSubview:background];
  //Now the ratainCount will be 2 since we added the imageview to the superview
  [background release];
 //i will release immediately so the retain count drops to 1
 . . . 


//in dealloc or viewDidDisaaper i will remove the imageview from its superview
//then the retainCount will become 0 and the instance will be deallocated.
//it works for we without any memory leakage
[background removeFromSuperview];