Представьте запуск detached-задачи из метода MainActor: унаследует ли её тело изоляцию MainActor?
Нет. Task.detached не наследует изоляцию текущего актора, поэтому его тело не выполняется автоматически на MainActor. Для доступа к состоянию MainActor нужен явный переход, например через MainActor.run или вызов actor-изолированного async-метода.
Структурированная конкурентность в Swift по умолчанию связывает дочерние задачи с контекстом родителя: они могут наследовать отмену, приоритет и изоляцию. Такой подход снижает число неявных гонок и упрощает управление жизненным циклом задач.
Task.detached нужен для намеренного запуска независимой задачи. Поэтому он не наследует контекст родителя автоматически: это делает границу изоляции явной, но одновременно возлагает на разработчика ответственность за безопасную передачу данных и переход к нужному актору.
Если создать detached-задачу из кода, изолированного MainActor, нельзя предполагать, что обращение к UI или другому состоянию MainActor будет безопасным. Прямой доступ нарушит правила изоляции и обычно будет отвергнут компилятором; обход проверки может привести к гонке данных или работе с UI не на том акторе.
Кроме того, detached-задача не получает автоматически отмену, task-local значения и приоритет родителя. Поэтому её следует применять только тогда, когда независимый жизненный цикл действительно нужен.
Обычная Task наследует часть контекста места создания, включая актуальную actor-изоляцию. Task.detached создаёт независимую неструктурированную задачу с неизолированным телом; сам факт запуска из MainActor этого не меняет.
В примере тело detached-задачи не является MainActor-изолированным. Только замыкание внутри MainActor.run исполняется на MainActor, после чего задача снова продолжает работу вне него. Сам переход не означает выполнение на конкретном потоке: гарантируется actor-изоляция, а не имя или идентификатор потока.
Замыкание detached-задачи должно удовлетворять требованиям безопасной передачи данных, поэтому захватываемые значения проверяются строже. Нельзя просто захватить изменяемое состояние MainActor или произвольный несамопередаваемый ссылочный объект; вместо этого передают снимок значения, Sendable-тип или обращаются к владельцу состояния через его actor.
Компромисс таков: detached-задача предоставляет независимость, но теряет полезное наследование контекста. Для большинства дочерних операций предпочтительнее обычная Task или структурированная конструкция; detached оправдана, например, для фоновой работы, не связанной с текущим actor-контекстом.
Метод контроллера, изолированный MainActor, запускает обработку большого набора данных. Разработчик выбирает Task.detached, чтобы не выполнять тяжёлую работу в UI-контексте, но замыкает в задаче ссылку на контроллер и позже напрямую меняет его состояние. Такой вариант опасен: контроллер не становится безопасным для фонового доступа, а его состояние нельзя считать защищённым только из-за запуска задачи.
Вариант с обычной Task сохраняет actor-изоляцию и безопасен для UI, но синхронный тяжёлый участок всё равно может блокировать MainActor. Вариант с detached-задачей и передачей только Sendable-снимка данных отделяет вычисление от UI; после завершения результат явно отправляется на MainActor.
Оптимальным будет второй вариант: detached-задача получает независимые входные данные, выполняет вычисление без доступа к контроллеру, а обновление UI выполняется отдельным изолированным переходом. Это сохраняет безопасность данных и не смешивает фоновую работу с состоянием интерфейса.
Нет. Отмена родительской задачи автоматически не отменяет Task.detached. Если независимую задачу нужно остановить, её дескриптор следует хранить и отменять явно либо передавать собственный сигнал отмены.
Асинхронный actor-изолированный метод вызвать можно, но вызов должен явно отражать возможную приостановку и переход к актору. Синхронный доступ к изолированному состоянию недопустим. Это правило предотвращает одновременное обращение к состоянию из разных исполнительных контекстов.
Ссылка сама по себе не переносит actor-изоляцию в новую задачу и не превращает объект в Sendable. Безопасность сохраняется только при обращении к объекту через его изоляцию, например вызовом его actor-изолированного метода. Если же объект передан с обходом проверок, ответственность за отсутствие гонок полностью лежит на разработчике.