为啥我的财产可能会泄漏,我该如何解决?

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 在您需要的时候留下来。我应该注意,您还拥有从名称以 allocnewcopymutableCopy 开头的方法返回的任何对象。

因此,查看您的代码,您可以看到您拥有使用 alloc 创建的 UIScrollView,但是当您将其存储在属性中时,您再次声明了所有权。这意味着内存永远不会被回收。通过调用autorelease,您在将对象分配给属性之前放弃对象的所有权,这意味着在dealloc 中调用release 将按预期工作。

我建议您阅读 Objective-C 编程语言文档的 Memory Management Programming Guide 和 Declared Properties 部分。

【讨论】:

谢谢你的回答 :) 遗憾的是不可能给两个人一个正确的答案!我会再读一遍:)

以上是关于为啥我的财产可能会泄漏,我该如何解决?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我打开 access 数据库 (.accdb) 时我的 winform 会调整大小,我该如何解决?

为啥我的导航标签会在悬停时移动?我该如何解决?我只想使用 css,

CSS3:为啥这个过渡不起作用,我该如何解决?

为啥我的搜索功能没有按预期工作,我该如何解决?

为啥 Main.storyboard 中会出现内部不一致,我该如何解决?

为啥我的 python pandas 数据框剥离方法不适用于尾随空格?我该如何解决?