nil, Nil, NULL, NSNull
Четыре «ничего»
Первые три — нулевые указатели, различающиеся только типом и соглашением об использовании; четвёртое — настоящий объект.
nil—(id)0, нулевой указатель на объект. Сообщениеnilбезопасно и возвращает ноль.Nil—(Class)0, нулевой указатель на класс (Class cls = Nil).NULL—((void *)0), нулевой C-указатель:char *,int *, блоки в C-API,NSError **аргумент (когда ошибка не нужна). Численно все три равны нулю, компилятор их не различает, но смешивать — плохой стиль.NSNull— синглтон[NSNull null], объект-плейсхолдер «значение отсутствует» для коллекций:NSArray/NSDictionaryне умеют хранитьnil(вставка — крашNSInvalidArgumentException), аNSNull— обычный объект, который можно положить и сравнить по указателю.
#import <Foundation/Foundation.h>
static void demo(void) {
id obj = nil;
Class cls = Nil;
char *cstr = NULL;
NSArray *row = @[@"Ann", [NSNull null], @42];
for (id value in row) {
if (value == [NSNull null]) { // синглтон — сравнение указателей
NSLog(@"missing");
}
}
NSLog(@"%@ %@ %s", obj, cls, cstr ? cstr : "");
}
Ловушка: [NSNull null] — живой объект, и [[NSNull null] length] — краш «unrecognized selector», а не 0, как было бы с nil. Поэтому значения из JSON нужно проверять на NSNull, а не на nil.
Продолжение ответа с кодом и уточняющими вопросами интервьюера — в приложении DevPrep.
Полный ответ — в DevPrep