Вызов метода для неинициализированного объекта (нулевой указатель)

  1. Каково нормальное поведение в Objective-C, если вы вызываете метод на объекте (указателе), который равен нулю (возможно, потому что кто-то забыл инициализировать его)? Должна ли она генерировать какую-то ошибку (segmentation fault, исключение исключающего указателя …)?
  2. Если это нормальное поведение, есть ли способ изменить это поведение (путем настройки компилятора), чтобы программа вызывала какую-либо ошибку / исключение во время выполнения?

Чтобы сделать это более ясным, о чем я говорю, вот пример.

Имея этот class:

@interface Person : NSObject { NSString *name; } @property (nonatomic, retain) NSString *name; - (void)sayHi; @end 

с этой реализацией:

 @implementation Person @synthesize name; - (void)dealloc { [name release]; [super dealloc]; } - (void)sayHi { NSLog(@"Hello"); NSLog(@"My name is %@.", name); } @end 

Где-то в программе я делаю это:

 Person *person = nil; //person = [[Person alloc] init]; // let's say I comment this line person.name = @"Mike"; // shouldn't I get an error here? [person sayHi]; // and here [person release]; // and here 

Сообщение, отправленное объекту nil вполне приемлемо в Objective-C, оно рассматривается как no-op. Невозможно пометить его как ошибку, потому что это не ошибка, на самом деле это может быть очень полезной особенностью языка.

Из документов :

Отправка сообщений в ноль

В Objective-C допустимо отправить сообщение в nil-it просто не влияет на время выполнения. В cocoa есть несколько моделей, которые используют этот факт. Значение, возвращаемое из сообщения в nil, также может быть действительным:

  • Если метод возвращает объект, то сообщение, отправленное в nil возвращает 0 ( nil ), например:

    Person *motherInLaw = [[aPerson spouse] mother];

    Если aPerson равен nil , то mother отправляется в nil и метод возвращает nil .

  • Если метод возвращает любой тип указателя, любой целочисленный скаляр размера меньше или равен sizeof(void*) , float , double , long double или long long , тогда сообщение, отправленное в nil возвращает 0 .

  • Если метод возвращает struct , как определено в Руководстве по вызовам функций Mac OS X ABI для возврата в регистры, тогда сообщение, отправленное в nil возвращает 0.0 для каждого поля в структуре данных. Другие типы данных struct не заполняются нулями.

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

С сайта Грега Паркера :

Если выполняется LLVM Compiler 3.0 (Xcode 4.2) или более поздняя версия

 Сообщения на нуль с возвращаемым типом |  вернуть
 Целые числа до 64 бит |  0
 Плавающая точка до длинного двойного |  0.0
 Указатели |  ноль
 Структуры |  {0}
 Любой тип _Complex |  {0, 0}

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

Начиная с первых версий Objective-C, сообщение nil всегда было безопасным no-op, которое возвращает nil. Из этого поведения зависит много кода.

  • Каков наилучший способ связи между controllerами?
  • Когда я должен использовать @synthesize явно?
  • objective C: Modulo bias
  • Чтение информации в формате MP3 с использованием объектива c
  • Как узнать модуль и показатель открытого ключа RSA на iPhone / objective C
  • @property сохранять, назначать, копировать, неатомически в Objective-C
  • Отключить автоматический подсчет ссылок для некоторых файлов
  • Пользовательский блок завершения для моего собственного метода
  • Как вы реализуете глобальную обработку исключений iPhone?
  • Преобразование цели-c typedef в его эквивалент строки
  • objective-C: BOOL vs bool
  • Давайте будем гением компьютера.