我有以下示例类:

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的保留计数吗?我错过了什么?

感谢您的帮助。

有帮助吗?

解决方案 5

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

其他提示

不要看保留计数。它们没用,只会误导你—你无法确定没有别的东西可以保留一个物体,你从某个地方得到的物品不会被分享。

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

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

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

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

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

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

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

你传入的是一个字符串常量,它实际上无法解除分配。我认为2147483647可能是UINT_MAX,这基本上意味着该对象无法释放。

我想你想这样做:

self.value = newValue;

将调用属性setter并导致副本发生。 “value = newValue”只需将指针值赋给实例变量。

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

嗯..我们越来越近了。

似乎newValue的保留计数也是2147483647。

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

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

FTA:

由@""返回的NSString需要被释放,还是自动释放? 都不是。 @"" -strings属于类NSConstantString ?,因此就像lisp中的原子一样;他们到处闲逛。也就是说,如果你使用@“牛”在代码中的两个不同的位置,它们将引用同一个对象。 我不认为-release或-autorelease对其中任何一个做任何事情。

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

#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;
}

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top