Swift 6中PreferenceKey数组类型defaultValue并发不安全如何解决?
Swift 6下PreferenceKey默认值的并发安全问题修复
首先看你定义的结构体代码:
struct DarkConnectorLineAnchor: Equatable { let anchor: Anchor<CGRect> } struct DarkStepPreferenceKey: PreferenceKey { static var defaultValue = [DarkConnectorLineAnchor]() static func reduce( value: inout [DarkConnectorLineAnchor], nextValue: () -> [DarkConnectorLineAnchor] ) { value.append(contentsOf: nextValue()) } }
在Swift 6语言模式下,这段代码会触发错误:
Static property 'defaultValue' is not concurrency-safe because it is nonisolated global shared mutable state
最优修复方案:将var改为let
你不需要把defaultValue声明为var,直接用let即可解决问题:
struct DarkStepPreferenceKey: PreferenceKey { static let defaultValue: [DarkConnectorLineAnchor] = [] static func reduce( value: inout [DarkConnectorLineAnchor], nextValue: () -> [DarkConnectorLineAnchor] ) { value.append(contentsOf: nextValue()) } }
原因是:
- Swift的数组是值类型,
PreferenceKey的defaultValue仅用于提供初始空数组,后续所有状态修改都是在reduce方法中操作传入的inout value参数(这是方法内部的局部状态,不是全局共享的defaultValue)。 - 全局静态
var会被视为共享可变状态,违反Swift 6的并发安全规则;而let修饰的静态属性是不可变的天然线程安全,完全符合要求。
其他备选方案(仅当确实需要可变defaultValue时)
如果你的业务场景真的需要defaultValue是可变的(这种情况在PreferenceKey的使用中非常罕见),可以通过actor隔离来修复:
@MainActor struct DarkStepPreferenceKey: PreferenceKey { static var defaultValue = [DarkConnectorLineAnchor]() static func reduce( value: inout [DarkConnectorLineAnchor], nextValue: () -> [DarkConnectorLineAnchor] ) { value.append(contentsOf: nextValue()) } }
但这种方案没必要,因为defaultValue在PreferenceKey的设计中只需要提供初始值,不需要被外部修改。
内容的提问来源于stack exchange,提问作者Amin
相关产品推荐
相关产品推荐

