Добавить объявление

Swift: как defer наконец-то подружился с асинхронностью

Иногда самые полезные изменения в языке - не громкие нововведения, а устранение небольших, но раздражающих неудобств. Те, что заставляют писать лишний код, нарушать логику или искать обходные пути. Именно таким изменением стало принятие SE-0493, которое разрешает использовать await внутри defer. На первый взгляд это техническая деталь. На деле - значимое упрощение для написания чистого и надежного асинхронного кода.

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

Что изменилось:


Теперь в async-функции вы можете писать так:

func loadData() async throws {
let resource = try await acquireResource()
defer {
await resource.release()
}
try await work(with: resource)
}

Как это работает:


Ключевая механика defer сохраняется, но теперь с поддержкой асинхронности:

  • Гарантия выполнения: блок defer выполнится при любом выходе из функции (успех, ошибка, возврат).

  • Ожидание завершения: если внутри defer есть await, функция дождется его завершения, прежде чем вернуть управление.

  • Ограничение: использовать await в defer можно только внутри async-контекста.

Почему это важно:


Раньше для асинхронной очистки приходилось либо дублировать код на всех путях выхода, либо использовать Task { }, который не гарантировал завершения операции. Теперь очистка ресурсов (закрытие сетевых соединений, сброс состояния, отмена операций) становится такой же простой и надежной, как и в синхронном коде.

Вывод:


Принятие SE-0493 - это пример зрелой эволюции языка. Вместо введения сложных новых концепций, Swift устраняет конкретное, давно назревшее несоответствие между синхронными конструкциями языка и его асинхронной парадигмой. Это изменение делает асинхронный код не только безопаснее, но и чище.
24.12.2025 48 541