2010-07-05 3 views
0

в течение дня теперь я смотрю на следующую рутину и не могу обхватить ее. У меня есть класс, такие как:NSNumber weirdo ....?

MyClass.h

... 
@interface MyClass : NSObject { 
    NSNumber *myNumber1; 
    NSNumber *myNumber2; 
} 

@property (nonatomic, retain) NSNumber *myNumber1; 
@property (nonatomic, retain) NSNumber *myNumber2; 

@end 

и м-файл

#import "MyClass.h" 
@synthesize myNumber1, myNumber2; 
@implementation MyClass 

-(id) init { 
    self = [super init]; 

    NSLog(@"Retain Counts myNumber1: %d, myNumber2: %d", [myNumber1 retainCount], [myNumber2 retainCount]); 

    myNumber1 = [NSNumber inbitWithint:10]; 
    myNumber2 = [NSNumber inbitWithint:2]; 

    NSLog(@"Retain Counts myNumber1: %d, myNumber2: %d", [myNumber1 retainCount], [myNumber2 retainCount]); 

    return self; 
} 
... 

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

MyClass * myGlobals = [[MyClass alloc] init];

=== >>> чудак >>>

Запуск подпрограммы У меня есть следующий вывод на консоль боксом,:

Retain Counts (before) - myNumber1: 0, myNumber2: 0 
Retain Counts (after) - myNumber1: 1, myNumber2: 26 

Как это может быть?

+0

Из любопытства, что происходит, когда вы меняете его на 'self.myNumber # = ...' вместо этого? Это не ответ, но я заинтересован в выходе. –

ответ

3

Если это ваш фактический код, он не должен работать вообще, он должен просто сбой. Если нет, вы должны вырезать и вставлять свой фактический код.

Однако, несколько вещей.

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

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

myNumber1 = [[NSNumber alloc] initWithInt:10]; // explicitly create the number 
myNumber1 = [[NSNumber numberWithInt:10] retain]; // take ownership through retain 
[self setMyNumber1:[NSNumber numberWithInt:10]]; // use the property accessors to deal with ownership and the convenience constructor to create the number 

Однако вы решите это сделать, вы должны в какой-то момент взять на себя ответственность объекта.

+0

однако использование [self ...] не является рекомендуемым подходом на этапе инициализации. Это может вызвать уведомление, в результате которого слушатели могут принять меры против объекта, который не полностью инициализирован. –

+0

@ Брэд Госс: ничто не должно в первую очередь наблюдать неинициализированный объект. Если что-то есть, то приложение имеет проблемы с гонкой независимо. –

+0

Я согласен с вашими комментариями, но ваш ответ не объясняет возникшую проблему. –

2

Вы никогда не должны смотреть на retainCount, так как это не имеет большого значения. Причина, по которой вы видите счет 26, заключается в том, что, вероятно, где-то в рамках (или даже в вашем собственном приложении) существуют другие экземпляры NSNumber, которые создаются с тем же int 2. Значение NSNumber является неизменным, и, как оптимизация NSNumber, вероятно, просто возвращает вам экземпляр, который он создал ранее. Пока вы не смотрите на retainCount, это не имеет значения для вас.

3

Не называйте `retainCount`

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

Абсолютное количество удержания - это деталь реализации, для которой у вас может не быть никакого контроля.

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

NSNumber кэширует подмножество общих ценностей.То есть для некоторых числовых значений существует один экземпляр NSNumber, который возвращается для всех запросов для получения экземпляра NSNumber, который обертывает это число.

Смежные вопросы