Оператор
defer Swift полезен для логики очистки. Он гарантирует, что блок кода будет выполнен при выходе из текущей области видимости, независимо от того, завершится ли выполнение нормально, возникнет ли ошибка или произойдет досрочный возврат.До выхода Swift 6.4 мы не могли выполнять асинхронные операции непосредственно внутри блока
defer. Начиная с версии Swift 6.4 это стало возможным.🔹 Ограничения defer без поддержки async
Рассмотрим функцию, которая открывает ресурс и должна закрыть его после завершения работы:
func processFile() async throws {
let file = try await openFile()
defer {
file.close()
}
try await process(file)
}Это работает, только если очистка выполняется синхронно. Однако многие современные API являются асинхронными. Если для закрытия файла требуется
await, приведенный выше код не сработает:defer {
await file.close() // Ошибка компилятора в Swift версии < 6.4
}
Чтобы устранить ошибку компилятора, нам пришлось перенести логику очистки в другое место:
let file = try await openFile()
do {
try await process(file)
await file.close()
} catch {
await file.close()
throw error
}
Помимо дублирования кода, это делает логику очистки менее очевидной, поскольку она отделена от получения ресурса.
🔹 Асинхронная очистка с помощью defer
Благодаря поддержке асинхронных операций с помощью defer мы можем расположить получение и очистку ресурсов рядом друг с другом:
func processFile() async throws {
let file = try await openFile()
defer {
await file.close()
}
try await process(file)
}Теперь операция очистки гарантированно выполняется при выходе из области видимости, но при этом поддерживается асинхронная работа.
🔹 Примечание по изоляции акторов|
Блок
defer наследует изоляцию актора от охватывающей его области видимости. Если окружающая функция выполняется на @MainActor, код очистки внутри defer также выполняется на @MainActor.📌 Лучшие вакансии для мобильных разработчиков
🐸 Библиотека мобильного разработчика
#АрхитектурныйКод #Swift