【问题标题】:Dot notation, release, and dealloc点表示法、释放和释放
【发布时间】:2011-08-26 13:44:30
【问题描述】:

@接口:

UIImageView *myImageView;

@property (nonatomic, retain) UIImageView *myImageView;

@实现:

@synthesize myImageView;

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
}

myImageView 的引用计数是多少? 2(1 来自 alloc,1 来自点符号保留)或 3(1 来自 alloc,1 来自点符号保留,1 来自 @property 保留)

这两个语句的引用计数是否相同?

self.myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];

myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];

另外,我假设您在 @implemenation 和 dealloc 方法中释放它们,对吗?


编辑:

我没有得到我想要的答案,也许我的问题很模糊。我了解点符号、@property、@synthesize 以及 setter 和 getter 的工作原理。我不明白的是使用“self”时会发生什么。并且没有“自我”。关于保留计数。我实际上在 myImageView 对象上运行了 retainCount 方法,它确认了我原来的“自我”。 case 的保留计数为两个(使用 alloc 和 property 保留,因此在那里使用 autorelease 可能是个好主意)。现在这导致另一个问题,如果我不使用自动释放,我该怎么做?在 viewDidLoad 中释放一次,在 dealloc 中再次释放仍然会导致内存泄漏,对吧?

self.myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
NSLog(@"retain count dot: %d", [myImageView retainCount]);

2011-05-17 10:01:14.915 测试[1249:207] 保留计数点:2

myImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
NSLog(@"retain count: %d", [myImageView retainCount]);

2011-05-17 10:03:14.715 测试[1278:207] 保留计数:1

【问题讨论】:

  • 不要将保留计数视为绝对值;将它们视为三角洲。 IE。 “alloc 产生一个引用计数 +1 的对象”、“self.myImageView = aView 将引用计数加一”、“release 将保留计数减一”.....
  • @bbum,理解,但我想了解的是直接使用属性评估器和 ivar 时的区别。我是否仍然需要在 viewDidLoad 中释放两者(因为我在那里分配),并在 dealloc 中再次释放它,因为它是一个保留属性。
  • 计算您造成的保留,并通过发布来平衡每个保留; +alloc 是一个,通过 setter 分配给属性是另一个......所以,是的,您需要两个版本或自动释放。就是这么简单;如果你保留,你必须释放。
  • 所以对于使用@property评估器的第二种情况,我必须释放它两次,一次在viewDidLoad中用于+alloc并在dealloc中释放用于保留?第一个案例呢?

标签: ios objective-c memory-management


【解决方案1】:

为了补充第一个答案,点符号设置器负责与释放旧对象和保留新对象有关的内存管理。在第二种情况下,您将有一个巨大的潜在内存泄漏,因为每次调用它时,retain 都会增加 1。点符号设置器不是这种情况。

但是,由于它保留了对象,因此您确实需要释放原始分配。

【讨论】:

    【解决方案2】:

    首先:您不应该对引用计数做出任何假设。这充其量只会产生误导。

    如果您使用属性访问 (self.myImageView = ...),那么它将自动保留,因此您在 viewDidLoad 中泄漏了 UIImageView。你应该使用类似的东西

    self.myImageView = [[[UIMageView alloc] init.... ] autorelease];
    

    您的最后一个示例(没有“点”访问)将直接修改 ivar,因此它不会泄漏这个新实例。 但是如果您之前不释放它,它会泄漏您覆盖的旧 imageView。

    我强烈建议始终使用属性访问。并且不要忘记在 dealloc 中进行清理:

    [myImageView release], myImageView = nil;
    

    有些人更喜欢self.myImageView = nil;,但这可能会有副作用。

    【讨论】:

    • 对于第一种使用属性访问的情况,我必须在 viewDidLoad 和 dealloc 中释放它,对吗? (因为引用计数为 2)。而对于第二种情况,我不需要在 viewDidLoad 中释放它,而只是在 dealloc 方法中?是我感到困惑的地方。
    • 基本上是的。但是点语法也会正确释放旧对象 - 真的很推荐。此外,您可能想使用 self.myImageView = nil;在 viewDidUnload 但那是另一回事。内存管理编程指南非常好读。
    【解决方案3】:

    不,它们不一样。第一个确实“保留”,从而增加了引用计数。所以要么你先把它分配给一个临时变量然后释放(在第一种情况下)[或者,添加'autorelease'并离开w/o临时变量],或者你检查是否已经分配了imageView(如果有 -释放它)在第二种情况下。

    【讨论】:

    • self.myImageView = alloc ... and [myImageView release] in viewDidLoad 和 myImageView = alloc ... and [myImageView release] 一样吗? .... 并在 dealloc 方法中再次释放?
    • 对不起,如果我上面的评论不清楚。我的意思是,对于这两种情况,你仍然需要释放两次,对吧?
    猜你喜欢
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 2012-01-18
    • 2013-07-23
    • 2011-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多