Ответ 1
Если вы привыкли к Java, это может показаться странным. Вы ожидали бы, что сообщение создания объекта должно было бы генерировать исключение, если оно терпит неудачу, вместо возврата nil
. Тем не менее, в то время как Objective-C в Mac OS X поддерживается обработка исключений; это дополнительная функция, которая может быть включена/выключена с помощью флага компилятора. Стандартные библиотеки написаны так, что они могут использоваться без обработки исключений: поэтому сообщения часто возвращают nil
, чтобы указывать на ошибки, а иногда также требуют, чтобы вы также передавали указатель на переменную NSError*
. (Это для разработки Mac, я не уверен, можно ли включить поддержку обработки исключений для iOS, учитывая, что вы также не можете включить сбор мусора для iOS.)
Раздел "Обработка отказа инициализации" в документе "Язык программирования Objective-C" объясняет, как должны работать программисты Objective-C с ошибками в инициализации/создании объекта: то есть return nil
.
Что-то вроде [NSData dataWithContentsOfFile: path]
может определенно вернуться nil
: документация для метода явно говорит об этом. Но я честно не знаю, вернется ли что-то вроде [NSMutableArray arrayWithCapacity: n]
nil
. Единственная ситуация, о которой я могу думать, когда это может произойти, когда приложение не работает. Но в этом случае я ожидаю, что приложение будет прервано попыткой выделить больше памяти. Я еще не проверил это, и вполне возможно, что в этом случае он возвращает nil
. В Objective-C вы можете безопасно отправлять сообщения на nil
, это может привести к нежелательным результатам. Например, ваше приложение может попытаться сделать NSMutableArray
, получить nil
вместо этого, а затем с радостью продолжить отправку addObject:
в nil
и выписать пустой файл на диск, а не один с элементами массива, как предполагалось, Поэтому в некоторых случаях лучше проверить, был ли результат сообщения nil
. Нужно ли делать это при каждом создании объекта, как это делает программист, которого вы цитируете, я не уверен. Лучше безопасно, чем жаль, возможно?
Изменить:. Я хотел бы добавить, что, хотя проверка того, что создание объекта преуспела, иногда может быть хорошей идеей, утверждая, что это не лучшая идея. Вы хотите, чтобы это также проверялось в версии версии вашего приложения, а не только в отладочной версии. В противном случае это портит точку проверки, поскольку вы не хотите, чтобы конечный пользователь приложения, например, завершался пустым файлом, потому что [NSMutableArray arrayWithCapacity: n]
вернулся nil
, и приложение продолжало отправлять сообщения в nil
возвращаемое значение. Утверждения (с assert
или NSAssert
) может быть удалены из версии выпуска с помощью флагов компилятора; Однако Xcode не включает эти флаги по умолчанию в конфигурации "Release". Но если вы захотите использовать эти флаги для удаления некоторых других утверждений, вы также удалите все ваши проверки на создание объектов.
Изменить: При дальнейших размышлениях это кажется более правдоподобным, чем я думал, что [NSMutableArray arrayWithCapacity: n]
вернет nil
вместо того, чтобы прервать приложение, когда недостаточно памяти. Basic C malloc
также не прерывается, но возвращает указатель NULL
, когда недостаточно памяти. Но я еще не нашел явного упоминания об этом в документации Objective-C по alloc
и аналогичным методам.
Изменить: Выше я сказал, что не уверен, что проверка на nil
необходима при каждом создании объекта. Но этого не должно быть. Именно поэтому Objective-C позволяет отправлять сообщения на nil
, которые затем возвращают nil
(или 0
или что-то подобное, в зависимости от определения сообщения): таким образом, nil
может распространяться через ваш код, несколько похожи к исключению, так что вам не нужно явно проверять nil
на каждое сообщение, которое могло бы вернуть его. Но это хорошая идея проверить его в точках, где вы не хотите, чтобы они распространялись, например, при записи файлов, взаимодействии с пользователем и т.д. Или в случаях, когда результатом отправки сообщения в nil
является undefined (как описано в документации по отправке сообщений на nil
). Я был бы склонен сказать, что это похоже на "версию бедствия" для распространения и обработки исключений, хотя не все могут согласиться с тем, что последнее лучше; но nil
ничего не говорит о том, почему произошла ошибка, и вы можете легко забыть проверить, где такие проверки необходимы.