我有以下代码:
NSString *bgImageName = [[Useful instance] getRootviewBackgroundImageName];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:bgImageName]];
imageView.clipsToBounds = YES;
CGRect rc = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[imageView setFrame:rc];
[self.view insertSubview:imageView atIndex:0];
[imageView release];
仪器在上面的代码中显示100%和第2行的内存泄漏,而在xcode 4.6中并非如此。我现在正在使用osx 10.8.5上的xCode 5
看来,我正确地释放了在第6行的视图中插入的已分配UIImageView
(第7行),所以我无法看到为什么intruments会引发内存泄漏警告。
有人知道为什么机构会(在我看来)提出错误的信息吗?
编辑:这是仪器截图,其中包含我泄漏对象的分配摘要:
UIKit
和QuartzCore正在保留我的对象,这是我泄漏UIImageView
的原因(或者我错误地认为这个假设?)。
将UIImageView
插入到视图(UIViewController
)中,该视图在我的xib文件中引用。将{@ 1}}添加到“self.view”后,如何控制添加UIImageView
后会发生什么?
答案 0 :(得分:5)
我在iOS 7上遇到了与Xcode 5相同的问题。经过一些实验,我注意到在针对iOS 6.1模拟器或运行iOS 7的设备(iPhone 5s)上运行时,Instruments没有显示内存泄漏。基于这些我只能得出结论,这是一个误报和iOS 7模拟器中的错误。
编辑:我更新到Xcode 5.0.1和OS X Mavericks之后不再出现此问题(我猜它是第一个修复它但无法确定的)。答案 1 :(得分:1)
Instruments显示触发泄漏对象分配的代码行,不实际泄露对象的原因。启用引用计数跟踪并查看该图像视图上的所有保留/释放事件。会有额外的保留(或缺失的释放)。
答案 2 :(得分:1)
我注意到您的RootViewController
实例正在发生这种情况。这真的是顶级视图控制器(例如你永远不会解散/弹出的控制器)吗?如果是这样,此分配摘要正确地告诉您图像视图仍然存在,并且很奇怪它被报告为泄漏。
如果视图控制器已被解雇,那么你有一个真正的泄漏(虽然问题不在你的问题的代码中:你已经正确地完成了)。您的分配摘要证明您的UIImageView
永远不会被破坏。如果视图控制器被正确解除并取消分配,则图像视图的分配摘要应如下所示:
注意,当我弹出视图控制器(在我的性能分析会话中为28秒)时,视图将被取消分配,因此UIImageView
也是(请参见两个突出显示的行)。
您可以从分配摘要中得出两个结论:
它没有显示您UIImageView
上的任何其他留言,表明此图片视图根本不是问题。不是你不小心在某处过度保留了这个图像视图的情况。
您没有看到removeFromSuperview
,这表明您的superview
本身永远不会被取消分配。
因此,问题是您的RootViewController
是否已从视图控制器层次结构中删除。如果是这样,那么您有一个泄漏或保留周期,可能是视图控制器本身,而不是此图像视图。
顺便说一句,听起来你已经熟悉了这些主题,但我经常将人们引荐到WWDC 2012视频iOS App Performance: Memory,这不仅描述了许多内存问题,而且还演示了如何使用跟踪这些(例如特别是快照)。
答案 3 :(得分:1)
我开始遇到同样的问题,我正在研究imageNamed。我发现过去有记忆问题。我终于使用[[UIImage alloc] initWithContentsOfFile:actualPath],其中actualPath来自主包。
答案 4 :(得分:1)
我认为@mishod有正确的答案。
我测试过,是的UIImageView setImage确实泄漏了!
如果你用
循环一堆图像 [yourImageView setImage:[UIImage imageNamed:@"sampleImage.png"]];
你可以看到仪器内存使用量的增加。 从那以后,这似乎是某种缓存 循环浏览所有图像内存使用情况将会持平。
正确的,或者至少是非泄漏的方式是:
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"sampleImage" ofType:@"png"];
UIImage *newImage = [[UIImage alloc] initWithContentsOfFile:thePath];
[yourImageView setImage:newImage];
我在我的代码上验证了这一点,因为我的APP正在循环很多 大图像文件。
答案 5 :(得分:1)
只是一个建议。不要在模拟器上运行仪器。在设备上执行此操作。有很多不同之处,你会看到更好/相关的结果。例如。模拟器的内存比真实设备的内存多得多。