Перейти к основному содержимому

5.14. Основные принципы обработки ошибок в Swift

Разработчику Архитектору

Основные принципы обработки ошибок в Swift

  1. Ошибки — это типы, соответствующие протоколу Error.
  2. Функции, которые могут выбрасывать ошибки, помечаются ключевым словом throws.
  3. Обработка ошибок осуществляется с помощью:
    • do-catch
    • try? (преобразует результат в Optional)
    • try! (игнорирует ошибку, вызывает панику при её возникновении)
  4. Нет иерархии наследования: вместо этого используются перечисления (enum) для группировки связанных ошибок.

Встроенные типы ошибок в стандартной библиотеке Swift

Swift не предоставляет большого количества предопределённых классов ошибок. Однако в Foundation и других системных фреймворках Apple определены следующие важные типы:

1. NSError (из Foundation)

  • Объектно-ориентированное представление ошибки, совместимое с Objective-C.
  • Содержит:
    • domain: String — домен ошибки (например, "NSCocoaErrorDomain")
    • code: Int — числовой код
    • userInfo: [String: Any] — дополнительные данные
  • Соответствует протоколу Error, поэтому может использоваться с throw.

2. Системные перечисления ошибок (в Foundation и других фреймворках)

Хотя Swift сам по себе не определяет глобальных классов вроде IndexError, Apple предоставляет типизированные ошибки через перечисления:

  • DecodingError, EncodingErrorFoundation) — ошибки сериализации/десериализации JSON и других форматов.
  • URLErrorFoundation) — ошибки сетевых запросов (например, отсутствие соединения, недопустимый URL).
  • POSIXError — ошибки уровня POSIX (например, ENOENT, EACCES), представлены как перечисление с кейсами:
    • .noSuchFileOrDirectory
    • .permissionDenied
    • .fileExists
    • и др.
  • CocoaError — ошибки, связанные с файловой системой, архивацией, свойствами и т.д.

Пример:

enum FileOperationError: Error {
case fileNotFound
case permissionDenied
case invalidFormat
}

3. Ошибки времени выполнения (аварийные завершения)

Эти ситуации не являются исключениями, а вызывают панику (fatal error):

  • Выход за границы массива: Index out of range
  • Принудительное разворачивание nil: Unexpectedly found nil
  • Деление на ноль (для целых чисел)
  • Нарушение precondition/assertion

Такие ошибки нельзя перехватить с помощью do-catch.


Особенности:

  • Нет общего базового класса ошибок — только протокол Error.
  • Перечисления (enum) — рекомендуемый способ определения пользовательских ошибок.
  • Совместимость с NSError: при вызове Objective-C API ошибки автоматически преобразуются в NSError, который соответствует Error.
  • Локализация: ошибки могут предоставлять локализованные описания через LocalizedError (подпротокол Error).

Пример использования:

enum NetworkError: Error {
case invalidURL
case noData
case decodingFailed
}

func fetchData() throws -> Data {
guard let url = URL(string: "https://example.com") else {
throw NetworkError.invalidURL
}
// ...
}

Нет типов ошибок

В Swift нет фиксированного списка «типов ошибок», аналогичного Python или Java, потому что:

  • Ошибки определяются как любые типы, соответствующие протоколу Error.
  • Стандартная библиотека Swift почти не содержит встроенных ошибок.
  • Основные системные ошибки предоставляются через Foundation в виде NSError, URLError, DecodingError, POSIXError и подобных типов.
  • Пользовательские ошибки создаются явно, чаще всего как enum.

Таким образом, модель ошибок в Swift — протокол-ориентированная и композиционная, без иерархии наследования.