我得到了一个在笔尖文件中设置的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 */
}
我已经弄清楚了问题所在。Apple 建议您保留通过 IBOutlet
s(在本例中为图像视图)连接到的对象。你说你没有这样做,但你应该遵循苹果的建议。您应该在一篇关于此问题的 iphonedevsdk.com 论坛帖子中概述了您应该的原因,该文章链接到一篇 Big Nerd Ranch 博客文章,该文章列出了所有内容。
在 iOS 上,如果您的插座有 setter,笔尖加载机制会使用资源库,如果没有,它会使用键值编码;具体来说,它使用 setValue:forKey:
,它保留了值(这是有记录的,但有些出乎意料)。图像视图(即视图控制器顶视图的子视图)由该视图保留。此键值设置过程也会保留它。因此,您不知道,您的对象有两个对图像视图的引用。Apple 提出保留属性建议,以便您知道视图正在保留。
您仍然不必担心保留计数本身,但您应该做以下两件事之一:将此IBOutlet
保留属性,并在viewDidUnload
和dealloc
中释放它(不过,每个都只有一次!),或者遵循 BNR 的建议并明确分配属性:
@property (assign, nonatomic) IBOutlet UIImageView *background;
在这种情况下,您不必自己释放它。在这两种情况下,请确保@synthesize
属性访问器。
以前:
不要看保留计数,如果没有检测到泄漏,那就不用担心了。UIKit 框架可能出于您不知道的原因保留视图。
此外,如果background
不是保留属性:
@property (retain) IBOutlet UIImageView *background;
你在 XIB 中创建它,你根本不应该发布它,因为你不拥有它。也就是说,您不对它的记忆负责;赋予您该责任的操作是:在对象上调用retain
,或使用名称以 alloc
、copy
、mutableCopy
或 new
开头的方法创建对象。
我对nib文件了解不多,我曾经像下面这样关注
background=[[UIImageView alloc] initWithFrame:CGRectMake(0,0,320,480)]; 现在雷丁计数为 1 [background setImage:[UIImage imageWithData:urlData]]; [某些视图添加子视图:背景]; 现在 ratainCount 将是 2,因为我们将图像视图添加到超级视图 [后台发布]; 我将立即释放,因此保留计数降至 1 . . .在 dealloc 或 viewDidDisaaper 中,我将从其超级视图中删除图像视图则保留计数将变为 0,并且实例将被解除分配。它适用于我们,没有任何内存泄漏[背景从超级视图中删除];