Меняет ли аннотация @Sendable способ владения захваченным экземпляром класса?
Нет. @Sendable задаёт требования конкурентной безопасности замыкания, но не меняет семантику владения: сильный захват продолжает удерживать экземпляр, а weak и unowned сохраняют свои обычные правила времени жизни.
При этом сам захват может быть запрещён компилятором, если захваченный тип не удовлетворяет требованиям Sendable. Это ограничение корректности передачи между конкурентными контекстами, а не механизм ARC.
До появления структурированной конкурентности основная задача ARC заключалась в автоматическом управлении временем жизни объектов внутри обычной модели ссылок. С появлением async/await, задач и изоляции исполнителей возникла отдельная проблема: безопасно ли передавать захваченные значения между потоками и конкурентными контекстами.
Для этого в Swift появился протокол Sendable и аннотация @Sendable. Они предотвращают небезопасную передачу изменяемого состояния, но не заменяют ARC и не превращают сильные ссылки в слабые.
Замыкание может жить дольше функции, в которой оно создано. Если оно сильно захватывает экземпляр класса, этот экземпляр будет удерживаться хранилищем замыкания до освобождения самого замыкания.
Добавление @Sendable не разрывает такое владение. Поэтому ошибочно считать, что передача callback в Task или другой конкурентный контекст автоматически предотвращает retain cycle либо сокращает время жизни объекта.
Обратная ошибка тоже опасна: использование weak только ради прохождения проверки конкурентности не делает доступ к объекту безопасным. Объект может исчезнуть до выполнения callback, а само состояние класса всё ещё может быть небезопасным для конкурентного доступа.
ARC учитывает операции владения, возникающие из захватов замыкания. Обычный захват экземпляра является сильным, если явно не указано иное. Такой захват увеличивает время жизни объекта независимо от того, имеет ли тип замыкания аннотацию @Sendable.
@Sendable проверяет, какие данные замыкание переносит между конкурентными контекстами. Значение захваченного типа должно быть безопасно передаваемо согласно правилам Swift: например, это может быть значение-тип с Sendable, актор или экземпляр класса с явно обеспеченной потокобезопасностью.
weak и unowned меняют именно владение и поведение при уничтожении объекта. weak не удерживает объект и обнуляется, тогда как unowned не удерживает объект и приводит к ошибке при обращении после его уничтожения. Ни одна из этих ссылок сама по себе не гарантирует потокобезопасность.
Пометка @unchecked Sendable отключает часть статической проверки и перекладывает ответственность на разработчика. Она не меняет ARC: сильные свойства и сильные захваты по-прежнему удерживают экземпляры, а ошибки синхронизации могут привести к гонкам данных.
Экран запускает отложенную операцию, callback которой передаётся в конкурентную задачу. Разработчик добавляет @Sendable и ожидает, что контроллер перестанет удерживаться задачей. В результате экран всё ещё не освобождается, потому что callback сильно захватывает контроллер.
Возможны три решения:
weak — цикл и лишнее удержание устраняются, но callback должен корректно обработать отсутствие экрана;@MainActor — повышает безопасность доступа, но требует правильно организовать границы взаимодействия.Обычно для UI выбирают слабый захват вместе с явной проверкой существования экрана, а изменяемое состояние передают через изолированный объект. Это отдельно решает две задачи: время жизни контроллера регулирует ARC, а безопасность доступа обеспечивает модель конкурентности.
Нет. @Sendable не анализирует граф владения как средство борьбы с циклами. Замыкание может сильно захватывать объект, объект — хранить это замыкание, и цикл останется. Для разрыва цикла нужны правильная архитектура владения, weak, unowned или явное освобождение callback.
Нет. Слабая ссылка только не удерживает объект и может быть обнулена. Она не синхронизирует чтение и изменение его свойств, не устраняет гонки и не гарантирует, что объект останется жив после отдельного чтения weak-ссылки.
ARC продолжит корректно управлять временем жизни ссылок, однако ARC не защищает данные от гонок. При отсутствии синхронизации возможны некорректные результаты, повреждение инвариантов и неопределённое с точки зрения логики приложения поведение. @unchecked Sendable допустим только тогда, когда потокобезопасность обеспечена вручную, например изоляцией, блокировкой или неизменяемым состоянием.