NSInteger установлен в 0, но возвращает nil

У меня есть NSInteger в моем классе, например

В @интерфейсе:

NSInteger currentRow;    

@property (assign) NSInteger currentRow;

В @реализации:

@synthesize currentRow;

Выполнение [self setCurrentRow:0], кажется, работает нормально, но использование [self currentRow] по какой-то причине просто возвращает null, не знаю почему. При использовании точек останова я вижу, что значение для currentRow равно 0, поэтому оно установлено нормально, но я не могу вернуть значение.


person BytesGuy    schedule 09.10.2011    source источник


Ответы (3)


В Objective-C важно различать объекты и примитивные типы.

Объект всегда хранится в виде указателя, который является местоположением объекта в памяти. Указатель — это просто число. С помощью NSLog вы можете использовать %p, чтобы увидеть это значение. Вы также можете отобразить его в отладчике, например: print myObject. Указатель отображается как шестнадцатеричное число с префиксом 0x. nil по сути является нулевым местоположением (0x0000). Когда вы выделяете объект любого типа, вы получаете указатель, который не равен нулю. Когда вы присваиваете объект переменной, вы просто копируете адрес памяти, а не дублируете объект. С помощью NSLog вы можете использовать %@ для распечатки description объекта. В отладчике вот так: print-object myObject.

Примитивные типы, такие как NSInteger, не являются объектами. Вместо сохранения указателя обычно вы просто сохраняете значение. Когда вы назначаете переменную NSInteger, вы делаете копию значения. Вы можете увидеть значение в отладчике, используя print. Или вот так: NSLog("%ld", (long)currentRow). Когда вы назначаете примитив, вы копируете его значение. Не используйте %@ или print-object с примитивами — они ожидают объекты.

(Я говорю «обычно вы просто сохраняете значение», потому что вы также можете создавать указатели на примитивные типы. Однако в таких ситуациях, как ваша, это не обязательно.)

[self currentRow] возвращает 0, как вы и установили. (Более того, поскольку Objective-C гарантирует инициализацию переменных экземпляра, он вернет 0, даже если вы не установили его.)

Проблема в том, что вы ожидаете указатель на объект. То, как вы исправляете свой код, зависит от того, как вы его используете:

  • Если вы используете print-object currentRow, измените его на print currentRow.
  • Если вы используете NSLog("%@", currentRow), измените его на NSLog(%"ld", (long)currentRow).
  • Если вы используете currentRow где-то еще, где требуется объект, измените переменную экземпляра и типы свойств на NSNumber *, тип объекта. Установите его с помощью [self setCurrentRow:[NSNumber numberWithInt:0]].
person paulmelnikow    schedule 10.10.2011

NSInteger не является объектом, он определен как int или что-то в этом роде. Таким образом, если вы установите для currentRow значение 0, а затем попытаетесь вернуть его, значение null (он же 0) будет абсолютно правильным значением.

person secondcitysaint    schedule 09.10.2011
comment
Это присваиваемое, а не сохраняемое свойство, поэтому оно должно работать с необъектными типами. - person Mattias Wadman; 10.10.2011
comment
И это работает! С точки зрения фактического значения в памяти null и 0 — это одно и то же. Попробуйте [self setCurrentRow:42], вы увидите, что [self currentRow] возвращает 42, просто убедитесь, что вы присваиваете результат NSInteger, а не объекту. - person secondcitysaint; 10.10.2011
comment
Да, абсолютно допустимо использовать свойства, которые не являются объектами, если вы определяете их как assign, чтобы sythesize пропустил танец сохранения/освобождения. - person Mattias Wadman; 10.10.2011

Метод получения будет синтезирован как - (NSInteger)currentRow, поэтому он должен работать нормально. Но как проверить, работает ли он? С NSLog(@"%@", ...)? Чем вы должны использовать %d.

Если вы хотите, чтобы это был объект, вы должны использовать свойства NSNumber и retain.

person Mattias Wadman    schedule 09.10.2011