TGViewer
YDC — Pizza Powered iOS YDC — Pizza Powered iOS @youngdacode · 241 subscribers
Post #159 233
😄 Когда хочется и новый стек трогать и легаси сильно не шатать

Если коротко, то тут статья, а тут макрос, который сгенерирует async/await обертки над старыми callback-based функциями.

Если чуть подробнее, то главная мысль не переписывать всё сразу, а создать мост между старым API и новым с помощью continuations и Swift-макросов, которые генерируют обёртки автоматически.

Если в вашем проекте сетевой слой и другие корные модули написаны через completion handlers, то полный рефакторинг повлечёт большой объём изменений, нагрузку на тестирование и риски для стабильности.

Используя bridge-подход можно включить async/await, сохранив обратную совместимость, поддержать постепенную миграцию и при этом не тормозить развитие продуктовых фич.


func info(
for id: String,
completion: @escaping (NetworkResponse<Response, BaseErrorResponse>) -> Void
) {
let request = Action.getInfo(id: id)
guard var url = pathProvider.createURL(type: request) else {
completion(.failure(.urlNotFound))
return
}

let endPoint = RequestEndpoint(
url: url,
parameters: request.parameters
)

networkClient.request(endpoint: endPoint, responseHandler: completion)
}


Добавляя withCheckedContinuation мы создаем мост между кодом, основанным на коллбэках, и современным миром асинхронности.

Параметр continuation это наша связь с асинхронным контекстом.

Для предоставления результата continuation.resume() нужно вызвать ровно один раз.

Можно вернуть значение через resume(returning:) или ошибки через resume(throwing:), а также resume(with result: sending Result<T,E>) если вы используется тип Swift Result.


func info(
for id: String
) async -> NetworkResponse<Response, BaseErrorResponse> {
return await withCheckedContinuation { continuation in
info(for: id) { result in
continuation.resume(returning: result)
}
}
}


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

UnsafeContinuation: Выключает проверки безопасности для лучшей производительности.

Плюсы:

↗️ Минимальные изменения в существующих модулях и обратная совместимость.

↗️ Пошаговая миграция: можно переводить отдельные вызовы/фичи.

↗️ Автоматизация через макросы уменьшает рутину и шанс ошибок.

↗️ Команда может продолжать продуктовую разработку параллельно с миграцией.

Минусы?

↘️ async/await обычно используют с throws, что даёт лаконичную обработку do/try/catch. Если старый нетворкинг возвращает Result<Response, Error>, то простая обёртка async -> Result не даёт преимуществ throws, клиенты всё равно будут делать switch/case или разбирать результат вручную.

↘️ resume нужно вызвать ровно один раз. Смешанная логика (ошибка сети + таймаут + cancellation + повтор попытки) повышает риск двойного resume или забытого resume, а это либо краш, либо подвисший await.

↘️ сам withCheckedContinuation имеет небольшой накладной расход и массовое применение без профилирования может дать неожиданный overhead. UnsafeContinuation быстрее, но теряет проверки.

🐊 Лично мне кажется, что на проекте с большим количеством легаси апи стоит с осторожностью внедрять такого рода кодогенерацию. С первого взгляда кажется удобным, но на деле может только добавить проблем. И было бы неплохо дописать макрос для нескольких реализаций метода с возвратом Result и с обработкой ошибок через throws.

📎 Modern Concurrency and Legacy code

#D #Arch #Legacy #Macros

👏
SwiftDifferently Modern Concurrency and Legacy code ‘We can’t touch that code — it’s all callback-based!’ Sound familiar? As a developer, you’ve probably heard this countless times, or even said it yourself.
  • 🔥 3
  • 💯 1
More from @youngdacode
  1. Mar 10, 2026😄 Статья CoordinatorKit 2.0: Production-Ready SwiftUI Navigation это пример честного разб…
  2. Mar 4, 2026☝️ 🚀 Как MCP-аналитика помогает AI-агентам кодирования принимать более «осознанные» решен…
  3. Feb 16, 2026☝️ В прошлом посте мы говорили про клиент-серверное взаимодействие: API, REST, запрос-отве…
  4. Feb 15, 2026☝️ 📦 Размер приложения — это не просто цифра в App Store Размер приложения напрямую влияе…
  5. Feb 13, 2026😏 Разберём разницу между some View и AnyView в SwiftUI. Тема не новая, но споры о правиль…
  6. Feb 9, 2026Вечернее-занимательное чтение. Пишет iOS разработчик с опытом, обзор на пост от iOS разраб…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →