Объектив C NSString * свойство сохраняет значение countd

У меня есть следующий примерный класс:

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? Что мне не хватает?

Спасибо за вашу помощь.

Ответы

Ответ 1

У вас есть ссылка на неизменяемую строку. Приложению не нужно копировать значение (строковые данные), поскольку оно неизменно. Если вы выполняете изменяемую операцию, например value = [newValue uppercaseString], тогда она должна скопировать биты в значение, а значение сохранить счет увеличено.

Ответ 2

Не смотрите на количество удерживаемых значений. Они не полезны и будут вводить вас в заблуждение - вы не можете быть уверены, что ничто другое не сохраняет объект, что объект, который вы получаете откуда-то, не разделяется.

Вместо этого сосредоточьтесь на собственности на объект и следуйте Cocoa правилам управления памятью в письме. Таким образом, управление вашей памятью будет правильным, независимо от того, какие оптимизации Cocoa могут делать за кулисами для вас. (Например, реализация -copy как только -retain для неизменяемых объектов.)

Кроме того, он критический, чтобы понять разницу между свойствами ваших объектов и переменными экземпляра внутри ваших объектов. В вашем вопросительном коде вы присваиваете значение переменной экземпляра. Эта переменная экземпляра такова: переменная. Присвоение ему будет вести себя как любое другое назначение переменной. Чтобы использовать свойство, вы должны использовать синтаксис точечного или синтаксического кода для фактического вызова метода set setter:

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

Код, сгенерированный для точечного синтаксиса и синтаксиса скобки, идентичен, и ни один из них не будет напрямую обращаться к переменной экземпляра.

Ответ 3

Вы проходите в строковой строке. Компилятор, вероятно, выделяет его в статической памяти и устанавливает значение удержания в максимально возможное значение.

Попробуйте использовать динамически выделенную строку и посмотрите, что произойдет.

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

Ответ 4

Вы передаете строчную константу, которая не может быть удалена. Я думаю, что 2147483647, вероятно, UINT_MAX, что в основном означает, что объект не может быть выпущен.

Ответ 5

Я думаю, вы хотите это сделать:

self.value = newValue;

который вызовет свойство setter и вызовет возникновение копии. "value = newValue" просто присваивает значение указателя переменной экземпляра.

Ответ 7

Хмм.. мы приближаемся.

похоже, что значение сохранения новогоValue также равно 2147483647.

Я попробовал динамически выделять строку вместо этого с теми же результатами подсчета результатов.

Я нашел полезную статью здесь: http://www.cocoadev.com/index.pl?NSString

FTA:

Должен ли быть выпущен NSString, возвращенный @"", или он автореализован? Ни. @ "- строки имеют класс NSConstantString?, и, таким образом, действуют как атомы в lisp; они болтаются. То есть, если вы используете @" корову" в двух отдельных местах вашего кода, они будут ссылаться на тот же самый объект. Я не думаю, что -release или -autorelease что-то делает с любым из них.

Если у меня есть "копия" на свойство, не должна ли она копировать содержимое целевой памяти в новую память с сохранением числа в 1? Казалось бы, атрибут copy ничего не делает в этом случае?

Ответ 8

#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

Ответ 9

В Cocoa многие неизменяемые объекты просто сохраняются, когда вы запрашиваете копию в той же зоне. Если объект не будет изменен (т.е. Его неизменность), то точный дубликат будет лишним.

В Objective-C класс константных строк разделен на класс Cocoa NSString, хотя он может быть подклассом NSString (я не уверен). Этот константный строковый класс может переопределять методы NSObject, такие как retain, release и dealloc, чтобы они ничего не делали, а также переопределяли retainCount, чтобы он всегда возвращал одинаковое число, UINT_MAX или так. Это связано с тем, что константная строка Objective-C создается в статической памяти. Он должен иметь общее общее поведение объекта Cocoa (при использовании Cocoa), чтобы его можно было добавить в массивы, используемые в качестве ключей к словарю и т.д., Кроме как в отношении управления памятью, поскольку оно было распределено по-разному.

Отказ от ответственности: я не знаю, о чем говорю.