do, try, catch
Часть раздела Логика и управление потоком путешествия по Swift на Coddy — урок 45 из 56.
Полная форма обработки ошибок — это do/try/catch:
enum DivError: Error { case byZero }
func divide(_ a: Int, _ b: Int) throws -> Int {
if b == 0 { throw DivError.byZero }
return a / b
}
do {
let r = try divide(10, 2)
print(r) // 5
} catch DivError.byZero {
print("can't divide by zero")
} catch {
print("unknown error")
}try ставится перед любым вызовом, который может выбросить ошибку. Если вызов выбрасывает ошибку, управление переходит к соответствующему catch; в противном случае выполнение продолжается после блока do.
Несколько блоков catch выполняются сверху вниз, и срабатывает первое совпадение, точно так же, как в switch. Пустой catch в конце является универсальным обработчиком; он почти всегда нужен, чтобы компилятор был доволен.
Задание
ЛегкоОпределите перечисление ParseError: Error с тремя вариантами: empty, notInteger и negative.
Определите функцию, выбрасывающую ошибку, parsePositive(_ s: String) throws -> Int, которая:
- Выбрасывает
.empty, еслиsпосле удаления пробелов пуста - Выбрасывает
.notInteger, еслиsне может быть преобразована вInt - Выбрасывает
.negative, если полученное значение< 0 - В противном случае возвращает полученное значение
Считайте одну строку из stdin и вызовите parsePositive в блоке do/catch. Выведите:
got: <n>в случае успехаerror: empty,error: not integerилиerror: negativeдля каждого случая
Для входных данных 42 результатом будет got: 42. Для пустой строки — error: empty. Для abc — error: not integer.
Шпаргалка
Обработка ошибок в Swift использует do/try/catch. Определяйте ошибки с помощью перечисления (enum), соответствующего протоколу Error, помечайте функции, которые могут выбрасывать ошибки, ключевым словом throws и используйте throw для вызова ошибки:
enum DivError: Error { case byZero }
func divide(_ a: Int, _ b: Int) throws -> Int {
if b == 0 { throw DivError.byZero }
return a / b
}
do {
let r = try divide(10, 2)
print(r) // 5
} catch DivError.byZero {
print("can't divide by zero")
} catch {
print("unknown error") // универсальный перехватчик
}tryдолжен предшествовать каждому вызову, который может выбросить ошибку.- Блоки
catchсопоставляются сверху вниз; срабатывает первое совпадение. - Обычный блок
catchв конце действует как универсальный перехватчик для всех остальных ошибок.
Попробуйте сами
let line = readLine()!
// TODO: enum ParseError; func parsePositive(_:) throws -> Int;
// do/try/catch с тремя ветками плюс универсальный блок catch
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Строки в деталях
Подсчет и индексыРегистр и удаление пробеловПоиск в строкахРазделение и объединениеЗамена подстрокИтоги — Проверка имени пользователя4Множества
Создание множествОбъединение и пересечениеРазность и симметрическая разностьПодмножество и надмножествоИтоги — Фильтр тегов7Проект — Трекер привычек
Обзор проектаОтметить выполнение10Проект — Движок викторины
Обзор проектаЗадаем вопросы2Диапазоны и шаги
Закрытые и полуоткрытыеШагМетоды диапазоновДиапазоны в SwitchИтоги: Сетка календаря3Словари
Объявление словарейБезопасный поискОбновление словарейИтерация по словарямГруппировка значенийИтоги — Инвентарь6Функции высшего порядка, часть 2
compactMapflatMapsorted(by:)Создание конвейеровПовторение — Таблица лидеров9Обработка ошибок
throws и Errordo, try, catchtry? и try!Проброс ошибокПовторение — Безопасный калькулятор