Цель C NSString * свойство сохранить количество странности - PullRequest
5 голосов
/ 31 декабря 2008

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

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

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

Ответы [ 9 ]

21 голосов
/ 01 января 2009

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

Вместо этого сконцентрируйтесь на владении объектом и следуйте правилам управления памятью какао к букве. Таким образом, ваше управление памятью будет правильным, независимо от того, какие оптимизации может сделать 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

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

11 голосов
/ 31 декабря 2008

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

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

NSString* string = [[NSString alloc] initWithString: @"some text"];
Test* test = [[Test alloc] initWithValue: string];
3 голосов
/ 31 декабря 2008

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

3 голосов
/ 31 декабря 2008

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

self.value = newValue;

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

3 голосов
/ 31 декабря 2008

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

2 голосов
/ 01 января 2009

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

0 голосов
/ 12 августа 2009

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

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

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

0 голосов
/ 12 августа 2009
#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

0 голосов
/ 31 декабря 2008

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

Похоже, что счетчик сохранения newValue также равен 2147483647.

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

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

FTA:

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...