Что такое Error в Swift?

Ответ

Error — это тип, представляющий ошибки времени выполнения в Swift. Все ошибки соответствуют протоколу Error.

Базовый пример с enum:

enum NetworkError: Error {
    case invalidURL
    case timeout(seconds: Int)
    case serverError(statusCode: Int)
}

// Функция, которая может выбросить ошибку
func fetchData(from urlString: String) throws -> Data {
    guard let url = URL(string: urlString) else {
        throw NetworkError.invalidURL
    }
    // ... реализация запроса
}

Обработка ошибок:

do {
    let data = try fetchData(from: "https://api.example.com")
    process(data)
} catch NetworkError.timeout(let seconds) {
    print("Таймаут через (seconds) секунд")
} catch NetworkError.serverError(let code) where code == 500 {
    print("Внутренняя ошибка сервера")
} catch {
    print("Неизвестная ошибка: (error.localizedDescription)")
}

Сокращённые формы:

// try? — возвращает nil при ошибке
if let data = try? fetchData(from: urlString) { /* обработка */ }

// try! — принудительное извлечение (крашнет при ошибке)
let data = try! fetchData(from: guaranteedValidURL)

// defer — гарантированное выполнение кода
func readFile() throws -> String {
    let file = openFile()
    defer { closeFile(file) } // Выполнится в любом случае
    return try parseFile(file)
}

Ответ 18+ 🔞

О, слушай, ну вот, блядь, пришло время поговорить про Error в Swift. Это, сука, такой тип, который олицетворяет все наши косяки и просчёты во время работы программы. Всякая хуйня, которая может пойти не так, должна соответствовать протоколу Error. Без этого нихуя не выбросишь.

Вот, смотри, как это обычно выглядит, на примере enum:

enum NetworkError: Error {
    case invalidURL
    case timeout(seconds: Int)
    case serverError(statusCode: Int)
}

// Функция, которая может тебе впендюрить ошибку
func fetchData(from urlString: String) throws -> Data {
    guard let url = URL(string: urlString) else {
        throw NetworkError.invalidURL
    }
    // ... тут типа запрос куда-то делается
}

А теперь, блядь, самое интересное — как эту ошибку ловить, чтобы всё не накрылось медным тазом:

do {
    let data = try fetchData(from: "https://api.example.com")
    process(data)
} catch NetworkError.timeout(let seconds) {
    print("Таймаут, блядь, через (seconds) секунд — сервер уснул")
} catch NetworkError.serverError(let code) where code == 500 {
    print("Ёпта, внутренняя ошибка сервера, всё пропало!")
} catch {
    print("Хуй знает что случилось, но случилось: (error.localizedDescription)")
}

Есть ещё, блядь, короткие пути, для ленивых или самоуверенных:

// try? — если похуй на ошибку, вернёт nil
if let data = try? fetchData(from: urlString) { /* ну ок, работаем */ }

// try! — это когда ты, блядь, на 146% уверен, что всё будет ок. Если нет — краш и пиздец.
let data = try! fetchData(from: guaranteedValidURL)

// defer — это, сука, магия. Код выполнится в любом случае, даже если всё пошло по пизде.
func readFile() throws -> String {
    let file = openFile()
    defer { closeFile(file) } // Вызовется в конце, хоть ты тресни!
    return try parseFile(file)
}

Вот и вся магия, ёпта. Либо ловишь ошибки, либо они ловят тебя.