Ответ
Методы, помеченные async, можно вызывать только из асинхронного контекста с использованием ключевого слова await. Основные способы создания такого контекста:
1. Внутри другой async функции:
func fetchUserData() async throws -> User {
// Вызов асинхронного метода с await
let data = try await networkService.fetchData(from: url)
return try JSONDecoder().decode(User.self, from: data)
}
2. В блоке Task:
Это основной способ запуска асинхронного кода из синхронного контекста (например, из метода viewDidLoad).
// Запуск асинхронной задачи
Task {
// Это асинхронный контекст
let user = await fetchUserData()
// Обновление UI должно быть на MainActor
await MainActor.run {
self.usernameLabel.text = user.name
}
}
3. В модификаторе .task в SwiftUI:
SwiftUI предоставляет специальный модификатор для безопасного запуска асинхронных задач, связанных с жизненным циклом View.
struct ContentView: View {
@State private var data: String = ""
var body: some View {
Text(data)
.task { // Асинхронный контекст, созданный SwiftUI
data = await loadData()
}
}
}
Важные правила:
awaitне блокирует поток: Он приостанавливает выполнение текущейasyncфункции, позволяя потоку выполнять другую работу, пока ожидается результат.- Вызов из синхронного контекста запрещен: Нельзя использовать
awaitпросто так. Нужно обернуть вызов вTaskили находиться внутриasyncфункции. - Обработка ошибок: Асинхронные функции, которые могут выбросить ошибку (
throws), требуют использованияtry await.