xcode Objective C NSString* 属性保留计数奇数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/403112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 18:27:13  来源:igfitidea点击:

Objective C NSString* property retain count oddity

iosobjective-cxcodecocoacocoa-touch

提问by Stefan Tannenbaum

I have the following example class:

我有以下示例类:

Test.h:

测试.h:

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

Test.m:

测试.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;
}

Which produces the following output:

产生以下输出:

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

I am calling it like:

我这样称呼它:

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

Shouldn't value have a retain count of 1? What am I missing?

值不应该保留计数为 1 吗?我错过了什么?

Thanks for your help.

谢谢你的帮助。

采纳答案by Stefan Tannenbaum

You've got a reference to an immutable string. Assignment doesn't need to copy the value (the string data) since it's immutable. If you do a mutable operation, like value = [newValue uppercaseString] then it should copy the bits into value, and value's retain count incremented.

您已经获得了对不可变字符串的引用。赋值不需要复制值(字符串数据),因为它是不可变的。如果您执行可变操作,例如 value = [newValue uppercaseString] 那么它应该将位复制到 value 中,并且 value 的保留计数增加。

回答by Chris Hanson

Don't look at retain counts. They're not useful and will only mislead you — you can't be certain that nothing else is retaining an object, that an object you get from somewhere isn't shared.

不要看保留计数。它们没有用处,只会误导您——您不能确定没有其他东西在保留一个对象,您从某处获得的对象没有被共享。

Instead, concentrate on object ownershipand follow the Cocoa memory management rulesto the letter. That way your memory management will be correct no matter what optimizations Cocoa may be doing behind the scenes for you. (For example, implementing -copyas just -retainfor immutable objects.)

相反,专注于对象所有权严格遵守Cocoa 内存管理规则。这样,无论 Cocoa 在幕后为您做什么优化,您的内存管理都是正确的。(例如,-copy-retain针对不可变对象实现。)

Furthermore, it's criticalto understand the difference between propertiesof your objects and instance variableswithin your objects. In your question's code, you are assigning a value to an instance variable. That instance variable is just that: a variable. Assigning to it will behave like any other variable assignment. To use the property, you must use either dot syntax or bracket syntax to actually invoke the property's setter method:

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

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

The code generated for the dot syntax and the bracket syntax is identical, and neither will access the instance variable directly.

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

回答by Stefan Tannenbaum

You are passing in a literal string. The compiler probably allocates it in static memory and sets the retain count to the maximum possible value.

您正在传递一个文字字符串。编译器可能会在静态内存中分配它并将保留计数设置为最大可能值。

Try a dynamically allocated string instead and see what happens.

试试动态分配的字符串,看看会发生什么。

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

回答by Stephen Darlington

You're passing in a string constant, which can't really be deallocated. I think that 2147483647 is probably UINT_MAX, which basically means that the object can't be released.

您正在传递一个字符串常量,它不能真正被释放。我觉得2147483647大概是UINT_MAX,基本上就是说对象不能释放了。

回答by Kristopher Johnson

I think you want to do this:

我想你想这样做:

self.value = newValue;

which will invoke the property setter and cause the copy to occur. "value = newValue" simply assigns a pointer value to the instance variable.

这将调用属性设置器并导致复制发生。"value = newValue" 只是为实例变量分配一个指针值。

回答by Kristopher Johnson

You shouldn't be paying attention to the retain counts, just follow the Cocoa memory management rules. http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html

您不应该关注保留计数,只需遵循 Cocoa 内存管理规则即可。http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html

回答by Kristopher Johnson

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    char *cstr = "this is a c string";

    NSString *str = [[NSString alloc] initWithUTF8String:cstr];
    NSLog(@"rc1: %d", [str retainCount]);

    [pool drain];
    return 0;
}

If you run the above code, it will display a retain count of 1

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

回答by dreamlax

In Cocoa, many immutable objects will simply retain themselves when you ask for a copy within the same zone. If the object is guaranteed not to change (i.e. its immutableness) then an exact duplicate is redundant.

在 Cocoa 中,当您在同一区域内请求副本时,许多不可变对象将简单地保留自己。如果保证对象不会改变(即它的不可变性),那么完全重复是多余的。

In Objective-C, the constant string class is separate to Cocoa's NSStringclass, although it may be a subclass of NSString(I'm not too sure). This constant string class may override NSObject's methods like retain, releaseand deallocso that they do nothing, and also override retainCountso that it always returns the same number, UINT_MAXor so. This is because an Objective-C constant string is created in static memory. It must have the overall general behaviour of a Cocoa object (when using Cocoa) so that it can be added to arrays, used as keys to a dictionary etc, except in regards to its memory management, since it was allocated differently.

在Objective-C 中,常量字符串类与Cocoa 的类是分开的NSString,尽管它可能是NSString(我不太确定)的子类。这个常量字符串类可以覆盖,等NSObject方法retain,以便它们什么都不做,也可以覆盖,以便它始终返回相同的数字,或者如此。这是因为在静态内存中创建了一个 Objective-C 常量字符串。它必须具有 Cocoa 对象的总体一般行为(使用 Cocoa 时),以便可以将其添加到数组中,用作字典的键等,除了内存管理方面,因为它的分配方式不同。releasedeallocretainCountUINT_MAX

Disclaimer: I don't actually know what I'm talking about.

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

回答by dreamlax

hmm.. we're getting closer.

嗯……我们越来越近了。

it appears that newValue's retain count is also 2147483647.

看来 newValue 的保留计数也是 2147483647。

I tried dynamically allocating the string instead with the same retain count results.

我尝试使用相同的保留计数结果动态分配字符串。

I found a helpful article here: http://www.cocoadev.com/index.pl?NSString

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

FTA:

自贸协定:

Does the NSString returned by @"" need to be released, or is it autoreleased? Neither. @""-strings are of class NSConstantString?, and thus act like atoms in lisp; they hang around. That is, if you use @"cow" in two separate places in your code, they will be referencing the very same object. I don't think -release or -autorelease does anything to either of them.

@"" 返回的 NSString 需要释放,还是自动释放?两者都不。@""-strings 属于 NSConstantString? 类,因此就像 lisp 中的原子;他们闲逛。也就是说,如果您在代码中的两个不同位置使用 @"cow",它们将引用同一个对象。我认为 -release 或 -autorelease 对它们中的任何一个都没有任何作用。

If I have "copy" on the property though, shouldn't it copy the contents of the target memory into new memory with a retain count of 1? It would seem the copy attribute does nothing in this case?

如果我在属性上有“复制”,它不应该将目标内存的内容复制到保留计数为 1 的新内存中吗?在这种情况下,似乎 copy 属性没有任何作用?