0Pricing
Swift Academy · Урок

defer с ошибками и ранним возвратом

Обеспечивайте очистку даже при выбросе ошибки или раннем возврате.

«defer с ошибками и ранним возвратом» — бесплатный урок Swift Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Swift Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Swift Academy содержит 4 уроков всего.

defer выполняется при возврате

Блок defer выполняется даже при досрочном выходе функции через return.

func check(_ value: Int) {
    defer { print("cleanup ran") }
    if value < 0 {
        print("negative, returning early")
        return
    }
    print("value is", value)
}
check(-5)

Очистка на каждом пути

Независимо от того, какой return сработает, отложенная очистка выполняется ровно один раз.

func classify(_ n: Int) {
    defer { print("done classifying") }
    if n == 0 { print("zero"); return }
    if n > 0 { print("positive"); return }
    print("negative")
}
classify(0)

defer выполняется при исключении

Когда функция выбрасывает исключение, зарегистрированные defers по-прежнему выполняются по мере выхода из областей видимости.

enum MyError: Error { case bad }
func risky(_ fail: Bool) throws {
    defer { print("cleanup on the way out") }
    if fail { throw MyError.bad }
    print("no failure")
}
try? risky(true)

Сочетание возврата и исключения

Независимо от того, возвращает ли функция управление обычным образом или выбрасывает исключение, срабатывает один и тот же defer.

enum E: Error { case oops }
func op(_ flag: Bool) throws -> Int {
    defer { print("op finishing") }
    if flag { throw E.oops }
    return 42
}
let r = try? op(false)
print(r ?? -1)

Очистка до распространения ошибки

defer выполняется до того, как выброшенная ошибка достигнет вызывающего кода, поэтому ресурсы освобождаются заранее.

enum E: Error { case fail }
func load(_ broken: Bool) throws {
    print("open")
    defer { print("close") }
    if broken { throw E.fail }
    print("read")
}
do {
    try load(true)
} catch {
    print("caught:", error)
}

Защита с помощью defer

Распространённый шаблон: получить ресурс, отложить очистку, а затем использовать guard с досрочными возвратами, которые всё равно запускают очистку.

func process(_ items: [Int]) {
    print("start")
    defer { print("finished") }
    guard !items.isEmpty else {
        print("nothing to do")
        return
    }
    print("processing", items.count, "items")
}
process([])

defer и циклы с исключениями

defer внутри цикла выполняется в конце каждой итерации, даже если более поздняя инструкция выбрасывает исключение.

enum E: Error { case stop }
func loop() throws {
    for i in 1...3 {
        defer { print("end", i) }
        if i == 2 { throw E.stop }
        print("body", i)
    }
}
try? loop()

Порядок при досрочном возврате

Несколько defers по-прежнему выполняются в порядке LIFO при досрочном возврате.

func multi(_ skip: Bool) {
    defer { print("A") }
    defer { print("B") }
    if skip { return }
    print("body")
}
multi(true)

Журналирование при сбое

Используйте defer, чтобы единообразно выполнить журналирование завершения или сбоя на всех путях выхода.

enum E: Error { case bad }
func attempt(_ fail: Bool) throws {
    var success = false
    defer { print("attempt success:", success) }
    if fail { throw E.bad }
    success = true
}
try? attempt(true)

Восстановление состояния при исключении

defer идеально подходит для отмены временных изменений состояния при выбрасывании исключения операцией.

enum E: Error { case fail }
func transaction(_ fail: Bool) throws {
    var inProgress = true
    defer { inProgress = false; print("inProgress:", inProgress) }
    if fail { throw E.fail }
    print("committed")
}
try? transaction(true)

Рекомендуемый подход

Полагаясь на defer для очистки, которая должна выполняться даже при досрочных возвратах и выброшенных ошибках, Вы предотвращаете утечки ресурсов на любом пути выхода.

enum E: Error { case x }
func safe(_ fail: Bool) throws {
    print("acquire")
    defer { print("release") }
    if fail { throw E.x }
    print("use")
}
try? safe(true)

Быстрая проверка

Проверьте defer с ошибками и возвратами.

Итоги

defer выполняется при каждом выходе из области видимости, включая досрочный return и выброшенную ошибку, до распространения ошибки. Поэтому это надёжное место для очистки и восстановления состояния на всех путях выхода с сохранением порядка LIFO.

func f(_ skip: Bool) {
    defer { print("cleanup") }
    if skip { return }
    print("work")
}
f(true)

Часто задаваемые вопросы

Урок «defer с ошибками и ранним возвратом» бесплатный?

Да — полный текст урока «defer с ошибками и ранним возвратом» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Swift Academy, подпишись на CoddyKit PRO. Курс Swift Academy содержит 4 уроков всего.

Чему я научусь в уроке «defer с ошибками и ранним возвратом»?

Обеспечивайте очистку даже при выбросе ошибки или раннем возврате. Ты практикуешь Swift Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Swift Academy?

Предыдущий опыт не требуется. Swift Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «defer с ошибками и ранним возвратом»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Swift Academy?

Да. Каждый урок Swift Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Как работает defer
  2. Порядок выполнения нескольких блоков defer
  3. defer для освобождения ресурсов
  4. defer с ошибками и ранним возвратом
← Назад к Swift Academy