为啥我的财产可能会泄漏,我该如何解决?
Posted
技术标签:
【中文标题】为啥我的财产可能会泄漏,我该如何解决?【英文标题】:Why is my property a potential leak and how can I fix it?为什么我的财产可能会泄漏,我该如何解决? 【发布时间】:2011-08-13 05:53:01 【问题描述】:我的 UIViewController 中有一个 UIScrollView,在我的 .h 文件中定义为:
#import <UIKit/UIKit.h>
@interface TestViewController : UIViewController <UIScrollViewDelegate>
@property (nonatomic, retain) UIScrollView * imageScrollView;
@end
然后在我的 .m 文件中,我有以下内容:
@synthesize imageScrollView = _imageScrollView;
我读到这将自动创建我通常会在 .h 文件中键入的 _imageScrollView? (UIScrollView * _imageScrollView)
我喜欢它,因为它从我的 .h 文件中删除了重复的代码。现在,在我的 loadView 中,我完成了剩下的工作:
self.imageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0 - 20.0 - 49.0)];
[_imageScrollView setDelegate:self];
[_imageScrollView setPagingEnabled:YES];
[_imageScrollView setBounces:NO];
[_imageScrollView setShowsHorizontalScrollIndicator:NO];
[_imageScrollView setShowsVerticalScrollIndicator:NO];
[_imageScrollView setContentSize:CGSizeMake(320.0 * 3.0, 480.0 - 20.0 - 49.0)];
在 dealloc 版本中和 nil:
- (void)dealloc
[_imageScrollView release], _imageScrollView = nil;
[super dealloc];
现在构建后 Xcode 告诉我这个:
Potential leak of an object allocated on line #linenumber
当我改变它时它会消失:
self.imageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0 - 20.0 - 49.0)];
到这里:
self.imageScrollView = [[[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 480.0 - 20.0 - 49.0)] autorelease];
为什么我在 dealloc 中释放它时需要自动释放它?我做错了什么?
此内存警告仅出现在安装了 Lion 的 iMac 上的 Xcode 中,而不出现在安装有雪豹的 Macbook 上...
【问题讨论】:
【参考方案1】:这是因为您的 imageScrollView
属性被声明为 retain
属性。这意味着当您设置它时,访问器(由@synthesize
生成)会自动保留该值。如果您不希望这种行为,您应该将您的属性声明为assign
。 (但您确实在这种情况下想要这种行为。)
无论如何,因此您的对象被保留了两次,一次在您的代码中,一次由访问器保留,因此它永远不会被释放。永远记住 self.imageScrollView =
就像 [self setImageScrollView:]
一样,那里发生的事情!
(最后,内存警告只发生在 Lion 上,因为旧 Xcode 没有注意到错误,而不是因为错误不存在。)
【讨论】:
啊,是的,现在对我来说很有意义..(我似乎无法在此处输入)如何避免自动释放?还是在这种情况下它是唯一(也是最好的)选择?通常,当我创建一个临时对象时,我会在完成后立即释放它。当有一种方法可以随时保留它时,用这样的东西填充自动释放池不是很糟糕吗? Autorelease 可能是您最好的选择。确实,自动释放池可能很慢,但前提是所讨论的代码实际上被调用了数千次。如果你在一个紧密的循环中分配了很多东西,那么你可能想要创建一个临时变量来指向你的新视图,将 imageScrollView 设置为它,然后在你的临时变量上调用 release。这样你可以在发布之前设置,所以你不需要自动释放。 (但同样,只有当你注意到它很慢时。) 你的意思是这样的: UIScrollView * imageScrollView = [[UIScrollView alloc] init]; [self setImageScrollView:imageScrollView]; [imageScrollView 发布];该应用程序并不慢(或者至少我没有注意到它),但对于任何未来的项目,我只想弄清楚这一点(但我认为是现在,再次感谢您!) 是的,就像那样(假设您还没有一个名为imageScrollView
的实例变量,您可能会这样做)。
@Rick van der Linde:在这种情况下,自动释放对性能的影响确实可以忽略不计。它本质上是一两个无操作消息发送。【参考方案2】:
您已经使用retain
选项定义了您的属性。这意味着当您将一个对象分配给该属性时,它将被保留——您“获得了该对象的所有权”。在这种情况下,这很好,因为您希望 UIScrollView
在您需要的时候留下来。我应该注意,您还拥有从名称以 alloc
、new
、copy
或 mutableCopy
开头的方法返回的任何对象。
因此,查看您的代码,您可以看到您拥有使用 alloc
创建的 UIScrollView
,但是当您将其存储在属性中时,您再次声明了所有权。这意味着内存永远不会被回收。通过调用autorelease
,您在将对象分配给属性之前放弃对象的所有权,这意味着在dealloc
中调用release
将按预期工作。
我建议您阅读 Objective-C 编程语言文档的 Memory Management Programming Guide 和 Declared Properties 部分。
【讨论】:
谢谢你的回答 :) 遗憾的是不可能给两个人一个正确的答案!我会再读一遍:)以上是关于为啥我的财产可能会泄漏,我该如何解决?的主要内容,如果未能解决你的问题,请参考以下文章
为啥我打开 access 数据库 (.accdb) 时我的 winform 会调整大小,我该如何解决?
为啥我的导航标签会在悬停时移动?我该如何解决?我只想使用 css,