Objective C NSString* свойство сохранять количество странностей

StackOverflow https://stackoverflow.com/questions/403112

Вопрос

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

Тест.h:

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

Тест.м:

@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"];

Разве значение value не должно иметь значение retain, равное 1?Что я упускаю из виду?

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

Это было полезно?

Решение 5

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

Другие советы

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

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

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

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;

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

Вам не следует обращать внимание на количество сохранений, просто следуйте правилам управления памятью Cocoa. http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html

хм..мы подбираемся все ближе.

похоже, что количество сохраняемых значений newValue также равно 2147483647.

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

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

Соглашение О свободной торговле:

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

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

#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 класс constant string является отдельным от класса Cocoa NSString класс, хотя это может быть подкласс NSString (Я не слишком уверен).Этот класс constant string может переопределять NSObjectтакие методы, как retain, release и dealloc так что они ничего не делают, а также переопределяют retainCount чтобы он всегда возвращал одно и то же число, UINT_MAX или около того.Это происходит потому, что постоянная строка Objective-C создается в статической памяти.Он должен иметь общее поведение объекта Cocoa (при использовании Cocoa), чтобы его можно было добавлять в массивы, использовать в качестве ключей к словарю и т.д., за исключением управления его памятью, поскольку оно было выделено по-другому.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top