Объектив 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" просто присваивает значение указателя переменной экземпляра.
Ответ 6
Вы не должны обращать внимание на количество удержаний, просто следуйте правилам управления памятью Cocoa. http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html
Ответ 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), чтобы его можно было добавить в массивы, используемые в качестве ключей к словарю и т.д., Кроме как в отношении управления памятью, поскольку оно было распределено по-разному.
Отказ от ответственности: я не знаю, о чем говорю.