3

当不在 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?
4

5 回答 5

7

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

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

此外,如果您有一个保留的属性,例如您的示例中的那个,您不能这样做 1. 直接访问底层实例变量,2. 做类似的事情

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

为什么?因为第一行根本没有必要——真的,为什么- [NSString stringWithString:]?您正在创建一个常量字符串,然后创建它的精确副本 - 这只是多余的。如果 Cocoa 的设计者是菜鸟,那么这行代码也会浪费内存——同一不可变字符串的两个完全相同的副本。幸运的是,实现 NSString 的人已经为这种情况做好了准备,并让这个方法检查它的参数是否是一个常量,如果是,则不做任何事情就返回它 - 所以你会返回相同的指针,但需要额外调用objc_msgSend- 这不是什么你要。

第二行也是错误的 - 同样,您没有按原样使用支持 ivar。此外,声明该属性是retain有原因的 - 如果您将一个对象设置为您的属性,该对象将由 setter 方法保留 - 无需手动保留它。

总而言之,你最好写

self.s = @"Hello World";

// ...

self.s = nil;

反而。

于 2012-08-21T06:50:12.560 回答
2

The correct way of doing this operation will be like this.

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. 

Deallocation of NSString will depend upon iOS AutoreleasePool, since you are releasing the retain count, next time when GC runs it will check the total retain count of that string and if it is not used anywhere else then it will delete that object.

于 2012-08-21T06:52:32.747 回答
1

所有retain调用都应与匹配的release. 通过分配给nil您放弃您保留的对象。

于 2012-08-21T06:50:21.547 回答
1

如果obj是一个属性,那么

self.obj = nil;

实际上会为您发布它。

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

 obj = nil;

那么你将不得不管理释放

于 2012-08-21T06:50:39.040 回答
1

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

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

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

注意:请记住,在您的示例代码中,您在分配对象后会保留该对象,因此如果您遵循Cocoa 内存管理策略,您现在拥有该对象的所有权。因此,一旦你设置了属性,你需要release或者autorelease对象来避免泄漏(因为通过使用属性,对象也将被它保留)。

于 2012-08-21T06:51:23.720 回答