Какой лучший способ бросить исключение в target-c / cocoa?
objective-c
cocoa
exception-handling
Стеф Тирион
источник
источник
@throw([NSException exceptionWith…])
подход, а более лаконичный.Слово предостережения здесь. В Objective-C, в отличие от многих похожих языков, вы, как правило, должны стараться избегать использования исключений для общих ошибок, которые могут возникнуть при нормальной работе.
Документация Apple для Obj-C 2.0 гласит следующее: «Важно: Исключения являются ресурсоемкими в Objective-C. Вы не должны использовать исключения для общего управления потоком данных или просто для обозначения ошибок (таких как недоступный файл)»
Концептуальная документация Apple по обработке исключений объясняет то же самое, но несколькими словами: «Важно: вам следует зарезервировать использование исключений для программирования или непредвиденных ошибок во время выполнения, таких как доступ за пределы коллекции, попытки изменить неизменяемые объекты, отправить недопустимое сообщение и потеря соединения с оконным сервером. Обычно такие ошибки исправляются с исключениями при создании приложения, а не во время выполнения. [.....] Вместо исключений используются объекты ошибок (NSError) и Механизм доставки ошибок Какао - рекомендуемый способ сообщить об ожидаемых ошибках в приложениях Какао. "
Причины этого частично заключаются в том, чтобы придерживаться идиом программирования в Objective-C (используя возвращаемые значения в простых случаях и параметры путем ссылки (часто класс NSError) в более сложных случаях), частично из-за того, что создание и отлов исключений намного дороже и И наконец (и, что наиболее важно), исключения Objective-C - это тонкая оболочка вокруг функций setjmp () и longjmp () в C, которые, по сути, портят вашу осторожную обработку памяти, смотрите это объяснение .
источник
Xcode распознает
@throw
операторы как точки выхода из функций, какreturn
операторы. Использование@throw
синтаксиса позволяет избежать ошибочных предупреждений « Control может достигнуть конца не пустой функции », которые вы можете получить[NSException raise:…]
.Кроме того,
@throw
может использоваться, чтобы бросить объекты, которые не относятся к классу NSException.источник
Что касается
[NSException raise:format:]
. Для тех, кто пришел из Java-фона, вы помните, что Java различает Exception и RuntimeException. Исключение является проверенным исключением, а RuntimeException не проверяется. В частности, Java предлагает использовать проверенные исключения для «нормальных условий ошибки» и непроверенные исключения для «ошибок времени выполнения, вызванных ошибкой программиста». Кажется, что исключения Objective C следует использовать в тех же местах, где вы использовали бы непроверенное исключение, а значения возврата кода ошибки или значения NSError предпочтительнее в тех местах, где вы будете использовать проверенное исключение.источник
Я думаю, что если вы согласны, лучше использовать @throw с вашим собственным классом, который расширяет NSException. Затем вы используете те же записи для try catch, наконец:
Apple объясняет, как создавать и обрабатывать исключения: перехват исключений
источник
Начиная с ObjC 2.0, исключения Objective-C больше не являются оболочкой для setjmp () longjmp () C и совместимы с исключением C ++, @try является «бесплатным», но создание и отлов исключений намного дороже.
В любом случае, утверждения (с использованием семейства макросов NSAssert и NSCAssert) генерируют исключение NSException, и это разумно для использования их в качестве состояний Райса.
источник
Используйте NSError для сообщения об ошибках, а не об исключениях.
Краткие сведения о NSError:
NSError позволяет кодам ошибок в стиле C (целым числам) четко идентифицировать основную причину и, надеюсь, позволяет обработчику ошибок устранить ошибку. Вы можете легко обернуть коды ошибок из библиотек C, таких как SQLite, в экземпляры NSError.
NSError также имеет то преимущество, что является объектом, и предлагает способ более подробного описания ошибки с помощью своего словарного элемента userInfo.
Но лучше всего то, что NSError НЕ МОЖЕТ быть выброшен, поэтому он поощряет более упреждающий подход к обработке ошибок, в отличие от других языков, которые просто подбрасывают «горячую картошку» все дальше и дальше вверх по стеку вызовов, после чего об этом можно сообщить только пользователю и не обрабатывается каким-либо осмысленным образом (если вы не верите в то, что следите за самым большим принципом сокрытия информации ООП, который есть).
Ссылка Ссылка: Ссылка
источник
Вот как я узнал об этом из «Руководства ранчо« Большой ботаник »(4-е издание)»:
источник
userInfo:nil
. :)Вы можете использовать два метода для вызова исключения в блоке try catch
или второй метод
источник
Я считаю, что вы никогда не должны использовать исключения для управления нормальным потоком программ. Но исключения должны создаваться всякий раз, когда какое-либо значение не соответствует желаемому значению.
Например, если какая-то функция принимает значение, и это значение никогда не может быть равным нулю, тогда лучше создать исключение, чем пытаться сделать что-то «умное» ...
Риз
источник
Вы должны генерировать исключения только в том случае, если вы попали в ситуацию, которая указывает на ошибку программирования, и хотите остановить запуск приложения. Поэтому лучший способ генерировать исключения - использовать макросы NSAssert и NSParameterAssert и убедиться, что NS_BLOCK_ASSERTIONS не определен.
источник
Пример кода для case: @throw ([NSExceptionceptionWithName: ...
}
С помощью:
Еще один более продвинутый вариант использования:
}
источник
Нет никаких причин не использовать исключения, как правило, в цели C, даже для обозначения исключений бизнес-правил. Apple может сказать, используйте NSError, кто заботится. Obj C существует уже давно, и когда-то ВСЯ документация C ++ говорила одно и то же. Причина, по которой не имеет значения, насколько дорого выбрасывать и перехватывать исключение, заключается в том, что время жизни исключения чрезвычайно мало и ... его ИСКЛЮЧЕНИЕ для обычного потока. Я никогда не слышал, чтобы кто-то говорил в моей жизни, что человеку, которому это исключение потребовалось много времени, чтобы его бросили и поймали.
Кроме того, есть люди, которые думают, что цель C сама по себе слишком дорога, и вместо этого код на C или C ++. Таким образом, говоря, что всегда использовать NSError плохо информирован и параноидален.
Но на вопрос этой ветки еще не ответили, какой ЛУЧШИЙ способ вызвать исключение. Способы возврата NSError очевидны.
Так ли это: [повышение NSException: ... @throw [[выделение NSException] initWithName .... или @throw [[MyCustomException ...?
Я использую проверенное / непроверенное правило здесь немного иначе, чем выше.
Важна реальная разница между (используя метафору java здесь) проверенным / непроверенным -> можно ли восстановиться после исключения. И под восстановлением я подразумеваю не просто НЕ крах.
Поэтому я использую пользовательские классы исключений с @throw для восстанавливаемых исключений, потому что, скорее всего, у меня будет какой-то метод приложения, который ищет определенные типы сбоев в нескольких блоках @catch. Например, если мое приложение представляет собой банкомат, у меня будет блок @catch для «WithdrawalRequestExceedsBalanceException».
Я использую NSException: повышение для исключений времени выполнения, так как у меня нет никакого способа восстановить это исключение, кроме как перехватить его на более высоком уровне и записать в журнал. И нет никакого смысла в создании собственного класса для этого.
Во всяком случае, это то, что я делаю, но если есть лучший, с таким же выразительным образом, я бы тоже хотел знать. В моем собственном коде, так как я давно перестал кодировать C hella, я никогда не возвращаю NSError, даже если я передал его через API.
источник