Arhn - архитектура программирования

Странный NSNumber?

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

МойКласс.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

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

05.07.2010

  • Из любопытства, что произойдет, если вместо этого изменить его на self.myNumber# = ...? Это не ответ, но меня интересует результат. 05.07.2010

Ответы:


1

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

Тем не менее, пара вещей.

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

Во-вторых, вы набрали что-то вроде 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

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

05.07.2010
  • однако использование [self ...] не рекомендуется на этапе инициализации. Это может вызвать уведомление, заставляющее слушателей предпринимать действия в отношении объекта, который не полностью инициализирован. 05.07.2010
  • @Brad Goss: в первую очередь ничто не должно наблюдать за неинициализированным объектом. Если что-то есть, то у приложения есть проблемы с гонкой независимо от этого. 05.07.2010
  • Я согласен с вашими комментариями, но ваш ответ не объясняет заданную проблему. 06.07.2010

  • 2

    Не вызывать `retainCount`

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

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

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

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

    05.07.2010

    3

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

    05.07.2010
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..