Завдання-C: Твердження проти винятку проти помилки


79

Коли в какао слід використовувати NSAssert, NSException, NSError?

Ось про що я думав:

NSAssert - При створенні будь-якої клієнтської програми, що використовується для програмістів, власна перевага для подвійної перевірки правил, домовленостей, припущень або попередніх умов та умов?

NSException - При створенні сторонньої бібліотеки на користь інших програмістів, які використовують бібліотеку, щоб вони одразу знали, коли введення недійсне?

NSError - При взаємодії із зовнішньою системою для отримання даних, таких як файл, база даних або веб-служба, які не гарантовано дадуть мені результат?

Відповіді:


103

NSAssert буде згенеровано виняток , коли він виходить з ладу. Отже, NSAssert має бути коротким і простим способом писати та перевіряти будь-які припущення, які ви зробили у своєму коді. Це (на мій погляд) не альтернатива виняткам, це просто ярлик. Якщо твердження не вдається, то у вашому коді щось пішло жахливо, і програма не повинна продовжуватися.

Зауважимо одне, що NSAssert не буде компілюватися у ваш код у збірці випуску, тому це зазвичай використовується для перевірки розумності під час розробки. Я насправді використовую власний макрос утвердження, який завжди активний.

Ви могли б використовувати @throwсвій власний NSException , коли ви точно хочете, щоб це було у збірці випуску, і в таких речах, як загальнодоступні бібліотеки / інтерфейс, коли деякі аргументи недійсні або вас викликали неправильно. Зверніть увагу, що це насправді не є звичайною практикою @catchвинятків і продовжуйте запускати свою програму. Якщо ви спробуєте це в деяких стандартних бібліотеках Apple (наприклад, Core Data), можуть статися погані речі. Подібно до твердження, якщо виникає виняток, програма, як правило, повинна закінчуватися досить швидко, оскільки це означає, що десь є помилка програмування.

NSErrors слід використовувати у ваших бібліотеках / інтерфейсах для помилок, які не є помилками програмування і які можна відновити. Ви можете надати інформацію / коди помилок абоненту, і він може чисто обробляти помилку, попереджати користувача, якщо це необхідно, і продовжувати виконання. Це, як правило, стосується таких помилок, як помилка "Файл не знайдений" або якась інша не фатальна помилка.


15
Якщо сказати сильніше, NSException не слід використовувати для позначення помилки, яку можна відновити.
bbum

28
Іншими словами: Obj-C's NSException == Клас помилки Java, і Obj-C NSError == Клас Java Exception. Ура за послідовність у термінах!
Tustin2121

2
Насправді NSAssert буде скомпільовано у ваш код, якщо ви не додасте NS_BLOCK_ASSERTIONS у свої попередньо скомпільовані файли префіксів. Прочитайте відповідь нижче (просто отримайте 50, щоб похвалити зараз :)
likid1412

3

Конвенція про какао полягає в тому, що виняток вказує на помилку програміста. Багато коду, включаючи фреймворк-код, не розроблений для належної роботи після видалення винятку.

Будь-яка помилка, яку слід виправити, представлена ​​символом NSError. Існує також система представлення NSErrors користувачеві. Як ви кажете, це переважно корисно для помилкових зовнішніх ресурсів.

Концептуально твердження - це твердження, яке даний присудок завжди оцінює як істинне; якщо цього не сталося, програма не працює. Хоча її поведінку можна змінити, NSAssertза замовчуванням сімейство є зручним способом кидання NSInternalInconsistencyExceptions (з можливістю вимкнення їх у збірках випусків).


2

Редагувати: У Xcode 4.2 твердження за замовчуванням вимкнені для збірок випуску,

Тепер NSAssert не буде скомпільовано у ваш код під час збірки випуску , але ви можете змінити його в налаштуваннях збірки


@Mike Weller, у вашій відповіді є одна помилка.

Зауважимо одне, що NSAssert не буде компілюватися у ваш код у збірці випуску , тому це зазвичай використовується для перевірки розумності під час розробки.

Насправді NSAssert буде скомпільовано у ваш код, якщо ви не додасте NS_BLOCK_ASSERTIONSдо своїх попередньо скомпільованих файлів префіксів.

У технічній примітці TN2190 ми можемо знайти:

Макроси, такі як NDEBUG, щоб вимкнути C assert або NS_BLOCK_ASSERTIONS, щоб вимкнути NSAssert Foundation, важливо вказати для попередньо скомпільованих файлів префіксів

Або ви можете прочитати це: Як дізнатися, чи вимкнено NSAssert у збірках випусків?


1

Загалом, винятки використовуються для сигналізації про помилки програміста - це речі, які не повинні відбуватися. Помилки використовуються, щоб сигналізувати про умови помилок, які можуть виникнути під час нормальної роботи програми - помилки користувача, в основному, або зовнішні умови, які повинні бути істинними, але можуть не бути. Отже, спроба видалити якийсь заблокований елемент у документі може бути помилкою, а спроба завантажити файл без підключення до Інтернету - помилкою, але спроба отримати доступ до недійсного елемента в колекції - винятком.

Твердження зазвичай використовуються при тестуванні, а AFAIK не використовується як загальний механізм обробки помилок, як інші.


Твердження можуть бути використані для наведення інваріантів. Наприклад, NSParameterAssert(someParam != nil);буде застосовувати інваріант, що вказаний параметр не повинен бути рівним нулю.
Лілі Баллард

@Kevin Ballard: Твердження зазвичай визначаються поза збірками випусків, або, принаймні, вони були останніми, коли я їх перевіряв, тому, як я вже сказав, вони не є загальним механізмом обробки помилок.
Чак

1
Вони можуть бути, але за замовчуванням вони не опускаються. Вам потрібно змінити налаштування збірки, щоб отримати таку поведінку.
Лілі Баллард
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.