Objective C NSString *属性保留奇数

我有以下的例子类:

Test.h:

@interface Test : UIButton { NSString *value; } - (id)initWithValue:(NSString *)newValue; @property(copy) NSString *value; 

Test.m:

 @implementation Test @synthesize value; - (id)initWithValue:(NSString *)newValue { [super init]; NSLog(@"before nil value has retain count of %d", [value retainCount]); value = nil; NSLog(@"on nil value has retain count of %d", [value retainCount]); value = newValue; NSLog(@"after init value has retain count of %d", [value retainCount]); return self; } 

其中产生以下输出:

 2008-12-31 09:31:41.755 Concentration[18604:20b] before nil value has retain count of 0 2008-12-31 09:31:41.756 Concentration[18604:20b] on nil value has retain count of 0 2008-12-31 09:31:41.757 Concentration[18604:20b] after init value has retain count of 2147483647 

我这样称呼它:

 Test *test = [[Test alloc] initWithValue:@"some text"]; 

不应该保留1的值吗? 我错过了什么?

谢谢你的帮助。

不要看保留计数。 他们没有用,只会误导你 – 你不能确定没有别的东西是保留一个对象,你从某个地方得到的对象是不共享的。

相反,专注于对象所有权 ,遵循cocoa内存pipe理规则的信件。 这样,不pipeCocoa在幕后为你做什么优化,你的内存pipe理都是正确的。 (例如,将-copy视为只为不可变对象保留)。

此外,了解对象的属性和对象中的实例variables之间的差异至关重要 。 在你的问题的代码中,你正在给一个实例variables赋值。 那个实例variables就是这样的:一个variables。 分配给它将performance得像任何其他的variables分配。 要使用该属性,必须使用点语法或括号语法来实际调用属性的setter方法:

 self.value = newValue; // this is exactly equivalent to the next line [self setValue:newValue]; // this is exactly equivalent to the previous line 

为点语法和括号语法生成的代码是相同的,都不会直接访问实例variables。

你正在传递一个文字string。 编译器可能将其分配在静态内存中,并将保留计数设置为最大可能值。

尝试一个dynamic分配的string,看看会发生什么。

 NSString* string = [[NSString alloc] initWithString: @"some text"]; Test* test = [[Test alloc] initWithValue: string]; 

你正在传递一个string常量,这个string不能真正被释放。 我认为2147483647可能是UINT_MAX,这基本上意味着对象不能被释放。

我想你想这样做:

 self.value = newValue; 

这将调用属性设置器并导致复制发生。 “value = newValue”只是将一个指针值赋给实例variables。

你有一个不可变string的引用。 赋值不需要复制值(string数据),因为它是不可变的。 如果你做了一个可变操作,比如value = [newValue uppercaseString],那么它应该将这些位复制到值中,并且值的保留计数递增。

你不应该留意保留计数,只要按照cocoa内存pipe理规则。 http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html

嗯..我们正在接近。

看来newValue的保留数也是2147483647。

我试着dynamic分配string,而不是相同的保留计数结果。

我在这里find了一篇有用的文章: http : //www.cocoadev.com/index.pl?NSString

FTA:

是否需要释放@“”返回的NSString,还是自动释放? 都不是。 @“” – string是NSConstantString类,因此在lisp中就像primefaces一样; 他们stream连忘返 也就是说,如果你在你的代码的两个不同的地方使用@“cow”,它们将引用同一个对象。 我不认为-release或者-autorelease对他们中的任何一个做任何事情。

如果我有属性“复制”,不应该将目标内存的内容复制到保留计数为1的新内存中吗? 在这种情况下,似乎复制属性什么也不做?

 #import <Foundation/Foundation.h> int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; char *cstr = "this is ac string"; NSString *str = [[NSString alloc] initWithUTF8String:cstr]; NSLog(@"rc1: %d", [str retainCount]); [pool drain]; return 0; } 

如果您运行上面的代码,它将显示一个保留计数1

在Cocoa中,当你在同一个区域内请求一个副本时,许多不可变的对象只会保留自己。 如果对象保证不变(即它的不可变性),那么确切的重复是多余的。

在Objective-C中,常量string类与Cocoa的NSString类是分开的,虽然它可能是NSString一个子类(我不太确定)。 这个常量string类可以覆盖NSObject的方法,比如retainreleasedealloc这样它们什么都不做,并且也覆盖retainCount ,使得它总是返回相同的数字, UINT_MAX左右。 这是因为在静态内存中创build了一个Objective-C常量string。 它必须具有Cocoa对象的总体行为(使用Cocoa时),以便可以将其添加到数组中,作为字典的关键字等,除了内存pipe理以外,因为它的分配方式不同。

免责声明:我实际上不知道我在说什么。