throws и Error
Часть раздела Логика и управление потоком путешествия по Swift на Coddy — урок 44 из 56.
Swift обрабатывает ошибки, заставляя функции объявлять, что они могут завершиться неудачей. Тело функции выбрасывает значение ошибки; вызывающая сторона должна её обработать.
Тип ошибки — это всё, что соответствует встроенному протоколу Error. Самый простой способ объявить свой собственный — использовать перечисление (enum):
enum InputError: Error {
case empty
case tooLong
}Функция, выбрасывающая ошибки, использует ключевое слово throws в своей сигнатуре и инструкцию throw в своем теле:
func validate(_ s: String) throws -> String {
if s.isEmpty { throw InputError.empty }
if s.count > 100 { throw InputError.tooLong }
return s
}Вы не можете вызвать функцию, выбрасывающую ошибку (throwing function), напрямую; компилятор заставляет вас обработать ошибку. В следующем уроке будет рассказано, как это сделать.
Задание
ЛегкоОпределите перечисление NumError: Error с двумя случаями: negative и tooBig.
Определите функцию, выбрасывающую ошибку, doubleSafely(_ n: Int) throws -> Int, которая:
- Выбрасывает
.negative, когдаn < 0 - Выбрасывает
.tooBig, когдаn > 100 - В противном случае возвращает
n * 2
Считайте одно целое число из stdin. Вызовите doubleSafely внутри блока do/catch (вы изучите точную форму на следующем уроке; пока используйте этот готовый скелет):
do {
let result = try doubleSafely(n)
print("ok: \(result)")
} catch NumError.negative {
print("negative")
} catch NumError.tooBig {
print("too big")
} catch {
print("unknown")
}Для входного значения 10 вывод будет ok: 20. Для -1 — negative. Для 500 — too big.
Шпаргалка
Определите типы ошибок, используя перечисление (enum), соответствующее протоколу Error:
enum InputError: Error {
case empty
case tooLong
}Пометьте функцию как выбрасывающую ошибку с помощью throws и используйте throw для генерации ошибки:
func validate(_ s: String) throws -> String {
if s.isEmpty { throw InputError.empty }
if s.count > 100 { throw InputError.tooLong }
return s
}Функции, выбрасывающие ошибки, должны вызываться с обработкой ошибок (например, do/catch); компилятор следит за этим.
Попробуйте сами
let n = Int(readLine()!)!
// TODO: enum NumError: Error { case negative, tooBig }
// func doubleSafely(_ n: Int) throws -> Int { ... }
// do { let r = try doubleSafely(n); ... } catch NumError.negative { ... } ...
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Строки в деталях
Подсчет и индексыРегистр и удаление пробеловПоиск в строкахРазделение и объединениеЗамена подстрокИтоги — Проверка имени пользователя4Множества
Создание множествОбъединение и пересечениеРазность и симметрическая разностьПодмножество и надмножествоИтоги — Фильтр тегов7Проект — Трекер привычек
Обзор проектаОтметить выполнение10Проект — Движок викторины
Обзор проектаЗадаем вопросы2Диапазоны и шаги
Закрытые и полуоткрытыеШагМетоды диапазоновДиапазоны в SwitchИтоги: Сетка календаря3Словари
Объявление словарейБезопасный поискОбновление словарейИтерация по словарямГруппировка значенийИтоги — Инвентарь6Функции высшего порядка, часть 2
compactMapflatMapsorted(by:)Создание конвейеровПовторение — Таблица лидеров9Обработка ошибок
throws и Errordo, try, catchtry? и try!Проброс ошибокПовторение — Безопасный калькулятор