Единственный полезный спецификатор исключения является "броском ()", поскольку в "не бросает".
Например:
[[NSData alloc] initWithContentsOfFile:@"this/path/doesn't/exist/"];
[[NSImage alloc] initWithContentsOfFile:@"unsupportedFormat.sjt"];
[NSImage imageNamed:@"AnImageThatIsntInTheImageCache"];
... и так далее. (Примечание: NSData может вызвать исключение, если файл не существует). Есть довольно много областей, в которых возврат nil является ожидаемым поведением при возникновении проблемы, и из-за этого стандартная практика - почти все время проверять наличие nil для согласованности.
Обычно, если ваш класс является производным непосредственно от NSObject
, в этом нет необходимости. Однако это хорошая привычка, так как если ваш класс является производным от других классов, их инициализаторы могут возвращать nil
, и если да, то ваш инициализатор может зафиксировать это и вести себя правильно.
И да. к сведению, я следую лучшим практикам и пишу их во всех моих классах, даже в тех, которые являются производными непосредственно от NSObject
.
Это необходимо для проверки того, что инициализация работала, оператор if возвращает истину, если метод инициализации не работает. return nil, так что это способ проверить правильность создания объекта. Несколько причин, по которым я могу думать о том, что инициализация может потерпеть неудачу, возможно, это переопределенный метод инициализации, о котором суперкласс не знает, или что-то в этом роде, хотя я бы не подумал, что это так часто. Но если это все-таки произойдет, лучше ничего не случиться, чем сбой, который, как я полагаю, всегда проверяется ...
Вы правы, вы часто можете просто написать [super init]
, но это не сработает для подкласса чего угодно. Люди предпочитают просто запоминать одну стандартную строку кода и использовать ее все время, даже когда это необходимо лишь иногда, и поэтому мы получаем стандартный if (self = [super init])
, который требует как возможность возврата nil и возможность возврата объекта, отличного от self
.
Эта конкретная идиома является стандартной, потому что она работает во всех случаях.
Хотя это и необычно, будут случаи, когда ...
[super init];
... возвращает другой экземпляр, таким образом требуя присваивание себе.
И будут случаи, когда он вернет nil, что потребует проверки на nil, чтобы ваш код не пытался инициализировать слот переменной экземпляра, который больше не существует.
Суть в том, что это задокументированный правильный шаблон для использования, и, если вы его не используете, вы делаете это неправильно.
Это своего рода резюме комментариев выше.
Допустим, суперкласс возвращает nil
. Что произойдет?
Ваш код рухнет в середине метода init
. (если только init
не делает ничего важного)
Ваш код, вероятно, упадет в какой-то момент позже, потому что ваш экземпляр nil
, а вы ожидали чего-то другого. Или же ваша программа поведет себя неожиданно, но без сбоя. О, Боже! Хотите ли вы этого? Я не знаю...
В вашей документации к коду(!) должно быть четко указано: "возвращает ... или nil", а остальная часть вашего кода должна быть подготовлена к работе с этим. Теперь это имеет смысл.