Вопрос проверяет понимание интероперабельности Swift и Objective-C, а также ограничений Swift Concurrency в смешанных проектах.
Swift Concurrency может использоваться рядом с Objective-C, но с ограничениями. Objective-C не знает про async/await и actor. Для интеграции используются completion-based API и специальные атрибуты. Swift-код может “оборачивать” Objective-C в async функции. Полной прозрачности нет, но совместное использование возможно и практикуется.
Большинство реальных iOS-проектов — смешанные, поэтому важно понимать границы Swift Concurrency.
Objective-C:
не знает про async/await
не понимает structured concurrency
не поддерживает actor
Поэтому Swift Concurrency не может напрямую экспортироваться в Objective-C.
Самый распространенный подход — написать Swift-обертку.
func loadData() async throws -> Data {
try await withCheckedThrowingContinuation { continuation in
legacyService.load { data, error in
if let data {
continuation.resume(returning: data)
} else {
continuation.resume(throwing: error!)
}
}
}
}
Так Objective-C код остается прежним, а Swift получает async/await.
Некоторые Objective-C API автоматически доступны как async:
URLSession
часть Foundation
Это достигается через специальные аннотации в SDK.
@MainActorДля совместимости с UIKit:
Swift-код помечается @MainActor
гарантируется выполнение на main thread
безопасная работа с UI
@MainActor
func updateUI() async {
// UI code
}
Actors:
нельзя использовать из Objective-C
нельзя объявлять @objc actor-методы
применимы только внутри Swift-части
Поэтому в смешанных проектах actors обычно используются внутри Swift-слоя, а наружу отдаются обычные методы.
На практике используют такой подход:
Objective-C слой остается как есть
Swift Concurrency используется в новых Swift-модулях
граница между слоями — completion-based API
Swift-код постепенно “оборачивает” legacy
Swift Concurrency и Objective-C могут сосуществовать, но не напрямую. Swift Concurrency используется внутри Swift-слоя, а взаимодействие с Objective-C происходит через адаптеры и обертки. Это компромисс, но он позволяет постепенно модернизировать кодовую базу, не переписывая legacy целиком и сохраняя стабильность проекта.