Ответ
Для комфортной работы с асинхронными задачами в iOS следует выбирать инструменты в зависимости от сложности и версии iOS.
1. Swift Concurrency (async/await) (iOS 13+, предпочтительно)
Современный, безопасный и читаемый подход.
// Объявление асинхронной функции
func fetchUserData() async throws -> User {
let (data, _) = try await URLSession.shared.data(from: userURL)
return try JSONDecoder().decode(User.self, from: data)
}
// Вызов в Task
Task {
do {
let user = try await fetchUserData() // Приостановка без блокировки потока
// Автоматический возврат на MainActor для обновления UI
await MainActor.run {
self.usernameLabel.text = user.name
}
} catch {
// Обработка ошибок
}
}
// Использование `async let` для параллельных задач
func loadDashboard() async throws -> Dashboard {
async let user = fetchUserData()
async let posts = fetchPosts()
return try await Dashboard(user: user, posts: posts)
}
2. Grand Central Dispatch (GCD) (DispatchQueue)
Универсальный, но более низкоуровневый подход для поддержки старых iOS или специфичных сценариев.
// Приоритет (QoS) и избегание блокировки main потока
DispatchQueue.global(qos: .userInitiated).async {
let image = self.applyHeavyFilter(to: rawImage)
DispatchQueue.main.async {
// Все UI-обновления — строго на главном потоке
self.imageView.image = image
}
}
3. OperationQueue
Для сложных зависимостей между задачами (очередность, отмена).
let downloadQueue = OperationQueue()
downloadQueue.maxConcurrentOperationCount = 2 // Ограничение параллелизма
let downloadOp = BlockOperation { /* Загрузка данных */ }
let parseOp = BlockOperation { /* Парсинг данных */ }
let updateUIOp = BlockOperation { /* Обновление UI на главном потоке */ }
parseOp.addDependency(downloadOp) // Парсинг только после загрузки
updateUIOp.addDependency(parseOp) // UI только после парсинга
OperationQueue.main.addOperation(updateUIOp) // UI-операция на главной очереди
downloadQueue.addOperations([downloadOp, parseOp], waitUntilFinished: false)
Рекомендации по выбору:
- Новый код для iOS 13+: Используйте Swift Concurrency. Он устраняет «ад колбэков», обеспечивает структурированную обработку ошибок и автоматическое управление потоками.
- Поддержка старых iOS или работа с C-библиотеками: Используйте GCD.
- Сложные цепочки зависимых задач с возможностью отмены и паузы: Используйте
OperationQueue. - Главное правило: Все операции, изменяющие UI, должны выполняться на главном потоке (
MainActor.run,DispatchQueue.main.async).