У модели обработки ошибок Swift 2 есть два важных момента: полнота и отказоустойчивость. Вместе они сводятся к вашему do
/ catch
заявлению необходимости ловить все возможные ошибки, а не только те , которые вы знаете , что вы можете бросить.
Обратите внимание, что вы не объявляете, какие типы ошибок может генерировать функция, а только выдает ли она вообще. Это проблема типа ноль-одна-бесконечность: поскольку кто-то определяет функцию, которую будут использовать другие (в том числе и ваше будущее), вам не нужно заставлять каждого клиента вашей функции приспосабливаться к каждому изменению в реализации вашей программы. функция, в том числе какие ошибки он может выдать. Вы хотите, чтобы код, вызывающий вашу функцию, был устойчивым к таким изменениям.
Поскольку ваша функция не может сказать, какие ошибки она выдает (или может выдать в будущем), catch
блоки, которые ее отлавливают, не знают, какие типы ошибок она может генерировать. Таким образом, в дополнение к обработке типов ошибок, о которых вы знаете, вам нужно обрабатывать те, которые вы не делаете, с помощью универсального catch
оператора - таким образом, если ваша функция изменит набор ошибок, которые она выдает в будущем, вызывающие по-прежнему будут ловить ее ошибки.
do {
let sandwich = try makeMeSandwich(kitchen)
print("i eat it \(sandwich)")
} catch SandwichError.NotMe {
print("Not me error")
} catch SandwichError.DoItYourself {
print("do it error")
} catch let error {
print(error.localizedDescription)
}
Но давайте не будем останавливаться на достигнутом. Подумайте еще об этой идее устойчивости. Как вы спроектировали свой бутерброд, вы должны описывать ошибки в каждом месте, где вы их используете. Это означает, что всякий раз, когда вы меняете набор ошибок, вы должны менять каждое место, где они используются ... не очень весело.
Идея определения ваших собственных типов ошибок состоит в том, чтобы позволить вам централизовать подобные вещи. Вы можете определить description
метод для ваших ошибок:
extension SandwichError: CustomStringConvertible {
var description: String {
switch self {
case NotMe: return "Not me error"
case DoItYourself: return "Try sudo"
}
}
}
И тогда ваш код обработки ошибок может попросить ваш тип ошибки описать себя - теперь каждое место, где вы обрабатываете ошибки, может использовать один и тот же код, а также обрабатывать возможные будущие случаи ошибок.
do {
let sandwich = try makeMeSandwich(kitchen)
print("i eat it \(sandwich)")
} catch let error as SandwichError {
print(error.description)
} catch {
print("i dunno")
}
Это также прокладывает путь для типов ошибок (или расширений для них) для поддержки других способов сообщения об ошибках - например, у вас может быть расширение для вашего типа ошибки, которое знает, как представить UIAlertController
сообщение об ошибке для пользователя iOS.