Что такое detached task и чем он отличается от обычного task
Что проверяют
Понимание структурированной конкурентности в Swift: что новая задача наследует от места создания, а что нет. Ответ сразу показывает, разбираетесь ли вы в изоляции акторов или ставите Task.detached там, где на обычный Task ругается компилятор.
Как отвечать
Обе конструкции создают неструктурированную задачу, то есть её жизненный цикл не привязан к вызывающему коду. Разница в наследовании контекста.
Task { } наследует изоляцию актора вызывающего кода, приоритет и значения task-local. Созданный внутри типа, помеченного @MainActor, он и выполнится на главном акторе.
Task.detached { } не наследует ничего: ни актора, ни приоритета, ни task-local. Замыкание стартует на общем пуле, а к изолированному состоянию обращается только через await.
Отмена у обоих одинакова и это частый уточняющий вопрос: неструктурированная задача не отменяется вместе с окружающей, отмена распространяется только в async let и группах задач. Значит, дескриптор задачи надо сохранить и вызвать cancel() самому.
let handle = Task.detached(priority: .background) { [weak self] in
await self?.cache.persist()
}Когда detached уместен: фоновая работа, которая не должна тянуть приоритет и изоляцию вызывающего и осмысленно переживает экран, откуда запущена. В остальных случаях честнее обычный Task и вынос тяжёлой работы в неизолированную функцию.
Где спотыкаются
Говорят, что обычная задача блокирует родительский контекст, а detached от блокировки спасает. Ничего она не блокирует: Task { } только планирует работу, а метод продолжает выполняться. Задерживает главный поток не задача, а синхронный тяжёлый код внутри неё.
Уходят в detached, чтобы «слезть с главного потока», и потом обновляют оттуда интерфейс. Возврат на главный актор нужен явный, через вызов изолированного метода или соответствующую обёртку, иначе получаете либо диагностику компилятора, либо падение в рантайме.
Затыкают detached предупреждения про Sendable и изоляцию. Предупреждение исчезает, гонка за данными остаётся, а вдобавок теряется наследование приоритета: работа, запущенная в ответ на действие пользователя, уезжает в фон и выполняется позже всего остального.