将nil分配给保留属性会释放与之关联的对象吗?

时间:2012-08-21 06:45:41

标签: ios memory-management memory-leaks nsstring

当不在ARC下时,对于以下代码,

·H

@property (nonatomic, retain) NSString *s;

的.m

NSString *m = [NSString stringWithString:@"Hellow, World"];
s = [m retain];

// later on
s = nil; <-- will this release the ref count on the string and hence get the string released?

5 个答案:

答案 0 :(得分:7)

当像这样使用时(即通过直接访问实例变量),那么不,它不会。但是,如果您使用属性的访问器方法([self setS:nil];self.s = nil;),那么是的,它会。

另请注意,释放对象并释放其内存是两件完全不同的事情。仅当对象没有更强的引用时才释放对象 - i。即你有最后一个引用它,然后你释放它。如果你释放它但它有其他引用(通过先前保留),那么它将不会被释放,只有它的引用计数将减1。

此外,如果您有保留属性,例如示例中的属性,则不能执行1.直接访问基础实例变量,2。执行类似

之类的操作
NSString *m = [NSString stringWithString:@"Hellow, World"];
s = [m retain];

为什么呢?因为第一行根本就没必要 - 真的,为什么- [NSString stringWithString:]?你正在创建一个常量字符串,然后创建它的精确副本 - 它只是多余的。如果Cocoa的设计师是新手,这条线也会浪费内存 - 同一个不可变字符串的两个精确副本。幸运的是,任何实现NSString的人都为这种情况做好了准备,并使这个方法检查它的参数是一个常量并返回它而不做任何事情 - 如果是 - 所以你得到了相同的指针,但是有一些额外的调用{{1} - 那不是你想要的东西。

第二行也是错误的 - 再次,你没有按原样使用支持ivar。此外,由于某种原因,该属性被声明为objc_msgSend - 如果您将对象设置为您的属性,则该对象将由setter方法保留 - 无需手动保留它。

总而言之,你最好写一下

retain

代替。

答案 1 :(得分:2)

执行此操作的正确方法将是这样的。

self.s = [NSString stringWithString:@"Hellow, World"]; // this will ensure that string is retained 

// later on
self.s = nil; // this will ensure that retain count is reduced. 

NSString的重新分配将取决于iOS AutoreleasePool,因为您正在释放保留计数,下次GC运行时它将检查该字符串的总保留计数,如果它未在其他任何地方使用,则它将删除该对象。

答案 2 :(得分:1)

所有retain来电都应与匹配的release配对。通过分配到nil,您将放弃保留的对象。

答案 3 :(得分:1)

如果 obj 是属性,那么

self.obj = nil;

事实上会为你释放它。

但如果不是属性或成员或局部变量

 obj = nil;

然后你必须管理发布

答案 4 :(得分:1)

在这种情况下,是的,假设您使用该属性并且不直接修改实例变量。如果在ARC下属性为strong而不是retain,情况也是如此。基本上,您的综合属性将如下所示:

- (void)setPropertyName:(NSString *)value {
  [value retain];
  [_propertyName release];
  _propertyName = value;
}

因此,如果为其分配新值,则将保留新值并释放旧值。如果新旧值相同,则几乎没有效果。

注意:请记住,在您的示例代码中,您在分配对象后保留该对象,因此如果您经过Cocoa memory management policy,您现在拥有该对象的所有权。因此,一旦设置了属性,就需要releaseautorelease对象以避免泄漏(因为通过使用属性,对象也将被它保留) )。