Swift6:创建符合Sendable协议的类时可变存储属性报错求解决
解决Sendable协议类中可变数组的报错问题
报错的核心原因是:遵循Sendable协议的类,其可变存储属性必须保证线程安全。普通的var counters: [Int]是可变的非线程安全属性,编译器无法确保多线程环境下的访问安全,因此触发错误。
以下是三种可行的解决方法:
方案一:改用Actor(Swift并发最佳实践)
Actor是Swift并发模型中专门用于线程安全状态管理的类型,天然遵循Sendable,内部状态会被自动保护,无需额外声明协议。
@Observable actor Manager { var hasContent: Bool { return counters.count > 0 } private var counters: [Int] = [] func lastNumber() -> Int? { return counters.last } func addCounter() { let number = Int.random(in: 1...50) counters.append(number) } }
适用场景:需要在多线程环境下安全修改状态的业务逻辑。
方案二:用@MainActor限制所有操作到主线程
如果你的Manager仅在主线程中使用,给类添加@MainActor标记,强制所有属性访问和方法调用都在主线程执行,避免多线程竞争。
@Observable @MainActor final class Manager: Sendable { var hasContent: Bool { return counters.count > 0 } private var counters: [Int] = [] func lastNumber() -> Int? { return counters.last } func addCounter() { let number = Int.random(in: 1...50) counters.append(number) } }
适用场景:UI相关的状态管理,所有操作天然绑定主线程。
方案三:手动用线程锁保护可变属性
如果必须使用普通类且需要支持多线程修改,可通过锁(如NSLock)包裹对counters的所有读写操作,确保同一时间只有一个线程访问该属性。
@Observable final class Manager: Sendable { var hasContent: Bool { lock.lock() defer { lock.unlock() } return counters.count > 0 } private var counters: [Int] = [] private let lock = NSLock() func lastNumber() -> Int? { lock.lock() defer { lock.unlock() } return counters.last } func addCounter() { let number = Int.random(in: 1...50) lock.lock() defer { lock.unlock() } counters.append(number) } }
适用场景:需要兼容旧代码或特殊线程模型的场景,但需确保所有读写操作都经过锁保护,避免遗漏导致数据竞争。
内容的提问来源于stack exchange,提问作者reza23
相关产品推荐
相关产品推荐

