Каковы основные принципы работы с async/await в Swift?

«Каковы основные принципы работы с async/await в Swift?» — вопрос из категории Многопоточность, который задают на 28% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Async/await — это модель асинхронного программирования в Swift, позволяющая писать линейный, легко читаемый код вместо использования completion handlers или цепочек Future/Promise.

Основные принципы:

  1. async — маркирует функцию как асинхронную. Такая функция может быть приостановлена (suspended).
  2. await — указывает точку приостановки, в которой выполнение может быть передано другим задачам, пока ожидается результат асинхронного вызова.
  3. Structured Concurrency: Асинхронные задачи выполняются в структурированной иерархии, что упрощает управление жизненным циклом и отмену.

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

// 1. Объявление асинхронной функции
func fetchUserData(from url: URL) async throws -> User {
    let (data, _) = try await URLSession.shared.data(from: url) // 'await' — точка приостановки
    return try JSONDecoder().decode(User.self, from: data)
}

// 2. Вызов в асинхронном контексте (Task)
Task {
    do {
        let user = try await fetchUserData(from: someURL)
        await MainActor.run { // Возврат в главный поток для UI-обновлений
            self.usernameLabel.text = user.name
        }
    } catch {
        print("Fetch failed: (error)")
    }
}

Ключевые преимущества:

  • Читаемость: Код выглядит как синхронный, нет "адской пирамиды" из замыканий.
  • Безопасность: Компилятор контролирует правильное использование асинхронного контекста.
  • Интеграция с ошибками: Полная поддержка try/catch.
  • Отмена задач: Встроенная поддержка через Task.checkCancellation() и Task.isCancelled.

Важное ограничение: Функции с await можно вызывать только из асинхронного контекста (другой async-функции или блока Task).