Не-Sendable передан через границу actor'а — разберите законные исправления и выберите одно
Вызов ниже не компилируется с ошибкой «non-Sendable type 'UserProfile' passed across an actor boundary». Перечислите законные исправления и примените одно.
Ограничения:
- Не глушите проверку через
@unchecked Sendable. - Хранилище должно остаться
actor; сохраните его APIsave.
final class UserProfile {
var name: String
var avatar: Data
init(name: String, avatar: Data) { self.name = name; self.avatar = avatar }
}
actor ProfileStore {
func save(_ profile: UserProfile) { /* persist */ }
}
func handoff(_ profile: UserProfile, to store: ProfileStore) async {
await store.save(profile) // ошибка: UserProfile не Sendable
}
Определите причину и примените одно исправление.
Законные исправления — сделать тип Sendable (значимый тип или неизменяемый final class); превратить его в actor; изолировать обе стороны в @MainActor; либо передать sending-значение. Лучше Sendable-значение — это убирает опасность в корне.
- ✗Хватаются за
@unchecked Sendableкак за единственное исправление - ✗Приводят к
Any, чтобы обойти проверку - ✗Думают, что
Taskглубоко копирует захваченные значения через границу
- →Когда превратить тип в
actorлучше, чем сделать егоSendable? - →Что гарантирует
sending, чего не даёт обычныйSendable?
Причина — UserProfile изменяемый и не Sendable, поэтому его нельзя передавать внутрь actor'а. Лучшее исправление — сделать модель Sendable-значением:
struct UserProfile: Sendable {
var name: String
var avatar: Data
}
actor ProfileStore {
func save(_ profile: UserProfile) { /* persist */ }
}
Значимый тип из Sendable-полей безопасно копируется через границу. Альтернативы — превратить UserProfile в actor, изолировать обе стороны в @MainActor или передать sending-значение; но Sendable-значение убирает опасность в корне.