Я не буду определяться с тем, что использовать, но вот некоторая информация о каждом из вариантов:
Исключения
Исключения в Obj-C на самом деле не предназначены для управления потоком программ. Из документации по обработке исключений :
Общая закономерность состоит в том, что исключения зарезервированы только для ошибок программиста, и программа, перехватывающая такое исключение, должна вскоре завершиться.
По этой причине я бы не рекомендовал использовать исключения @try
/ @catch
только для проверки правильности работы метода.
У вас также есть несколько опций для обработки исключений , в дополнение к настройке высокоуровневого обработчика исключений .
Ошибка
Ошибки обычно используются тремя способами:
Методы делегирования
Объект может просто передать NSError своему делегату в назначенном обратном вызове обработки ошибок:
- (void)myObject:(MyObject *)obj didFailWithError:(NSError *)error;
После этого делегат может предпринимать любые соответствующие действия, включая, возможно, отображение сообщения для пользователя. Этот шаблон обычно используется в асинхронных API на основе делегатов.
Выходные параметры
Чаще всего они используются в сочетании с логическим возвращаемым значением: если возвращаемое значение равно NO
, то объект NSError можно проверить для получения дополнительной информации об ошибке.
- (BOOL)performTaskWithParameter:(id)param returningError:(out NSError **)error;
Где один из возможных вариантов использования будет:
NSError *error;
if (![myObject performTaskWithParameter:@"param" returningError:&error]) {
NSLog(@"Task failed with error: %@", error);
}
(Некоторые люди также предпочитают сохранять логический результат в переменной перед проверкой, например BOOL success = [myObject perform...];
.) Из-за линейного характера этого шаблона его лучше использовать для синхронных задач.
Обработчики завершения на основе блоков
Довольно недавний шаблон с момента появления блоков, но довольно полезный:
- (void)performAsynchronousTaskWithCompletionHandler:(void (^)(BOOL success, NSError *error))handler;
Используется так:
[myObject performAsynchronousTaskWithCompletionHandler:^(BOOL success, NSError *error) {
if (!success) {
// ...
}
}];
Это сильно варьируется: иногда вы не увидите логический параметр, только ошибку; иногда в блок обработчика не передаются аргументы, и вы просто проверяете свойство состояния объекта (например, так работает AVAssetExportSession ). Этот шаблон также отлично подходит для асинхронных задач, когда требуется блочный подход.
Обработка ошибок
Какао в Mac OS X имеет довольно тщательный путь обработки ошибок . Существует также удобный метод NSAlert + (NSAlert *)alertWithError:(NSError *)error;
. На iOS класс NSError все еще существует, но нет тех же самых удобных методов для обработки ошибок. Возможно, вам придется многое сделать самостоятельно.
Прочтите Руководство по программированию обработки ошибок для получения дополнительной информации.
Возвращается ноль
Это часто используется в сочетании с параметрами NSError out; например, метод NSData
+ (id)dataWithContentsOfFile:(NSString *)path
options:(NSDataReadingOptions)mask
error:(NSError **)errorPtr;
Если чтение файла не удается, этот метод возвращает nil
, и дополнительная информация сохраняется в ошибке.
Одна из причин, по которой этот шаблон особенно удобен, заключается в том, что ноль сообщений , что может быть безопасно сделано без эффекта в Obj-C. Я не буду вдаваться в подробности о том, почему это полезно, но вы можете прочитать об этом больше в других разделах. (Просто убедитесь, что вы нашли актуальную статью; раньше было так, что методы, возвращающие значения с плавающей запятой, не обязательно возвращали бы 0 при отправке в nil, но теперь они делают, как описано в документации.)