Почему в продакшн коде иногда не все асинхронные результаты возвращаются и как это исправить
Что проверяют
Умеете ли вы искать причину, а не добавлять задержки и повторы наугад. Вопрос практический: интервьюер ждёт конкретных механизмов потери результата в Swift и того, как вы их ловите, а не рассуждений про многопоточность вообще.
Как отвечать
Перечислить типовые причины и сразу способ лечения.
- Колбэк вызывается не на всех ветках. Ранний выход из
guardбез вызова обработчика, и вызывающий ждёт вечно. Переход наasync/awaitснимает проблему: возврат обеспечивает компилятор. - Несбалансированные
enterиleaveуDispatchGroup. Лишний вход, иnotifyне сработает никогда, лишний выход уронит приложение. - Результаты копятся в общий массив из разных очередей, и часть записей теряется. Накапливать надо на одной последовательной очереди, в акторе, а лучше через группу задач.
- Задача отменена вместе с экраном. Модификатор
taskотменяет работу при исчезновении вью, и результат просто не приходит. - Конструкция
guard let self else { return }в колбэке: объект умер, результат выброшен молча.
try await withThrowingTaskGroup(of: Item.self) { group in
for id in ids { group.addTask { try await load(id) } }
var items: [Item] = []
for try await item in group { items.append(item) }
return items
}При переносе старого кода на конкурентность стоит брать withCheckedContinuation: он громко ругается на двойное возобновление, тогда как небезопасный вариант молча портит память.
Где спотыкаются
Объясняют пропажу гонкой потоков и заворачивают всё подряд в переход на главную очередь. Если обработчик не вызван ни разу, поток ни при чём: результата нет вовсе, и никакая синхронизация его не создаст.
Ждут, что группа задач вернёт результаты в порядке добавления. Она отдаёт их по мере готовности, и если складывать значения по индексу цикла, часть затрётся. Порядок восстанавливают, возвращая из задачи пару из ключа и значения.
Считают отмену ошибкой и гасят её общим перехватом. В логах при этом пусто, на экране пустой список, а причина не видна: отмену надо отличать от сетевого сбоя и не показывать пользователю как ошибку.