Xcode 16.2 Beta 2中onPreferenceChange无法使用,Swift6下如何解决?
Swift 6模式下Xcode 16.2 Beta 2中
onPreferenceChange的适配方案 问题场景
在Xcode 16.1中可正常运行的视图代码,在Xcode 16.2 Beta 2的Swift 6语言模式下,onPreferenceChange的闭包会抛出错误:"Main actor-isolated property 'height' can not be mutated from a Sendable closure"。
对比两个版本的onPreferenceChange签名差异:
- Xcode 16.1签名:
@inlinable nonisolated public func onPreferenceChange<K>(_ key: K.Type = K.self, perform action: @escaping (K.Value) -> Void) -> some View where K : PreferenceKey, K.Value : Equatable
- Xcode 16.2 Beta 2签名新增
@Sendable修饰,但未添加@MainActor:
@inlinable nonisolated public func onPreferenceChange<K>(_ key: K.Type = K.self, perform action: @escaping @Sendable (K.Value) -> Void) -> some View where K : PreferenceKey, K.Value : Equatable
这种变化导致闭包无法直接修改Main Actor隔离的视图属性,尝试用Task包裹赋值操作还会触发**"EXC_BAD_ACCESS code=2"**崩溃:
.onPreferenceChange(HeightKey.self) { height in Task { @MainActor in self.height = height } }
原视图代码:
struct HeightKey: PreferenceKey { static var defaultValue: CGFloat { .zero } static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = nextValue() } } struct ContentView: View { @State private var height: CGFloat = 0 var body: some View { VStack { Text("Title") .background( GeometryReader { proxy in Color.clear .preference(key: HeightKey.self, value: proxy.size.height) } ) .onPreferenceChange(HeightKey.self) { height in self.height = height } Text("Height: \(height)") } } }
可行适配方案
直接给onPreferenceChange的闭包添加@MainActor修饰,让闭包在Main Actor上下文执行,即可安全修改视图的@State属性,且不会触发崩溃:
.onPreferenceChange(HeightKey.self) { @MainActor height in self.height = height }
也可以采用完整写法,将闭包整体标记为@MainActor:
.onPreferenceChange(HeightKey.self, perform: { @MainActor height in self.height = height })
原理说明
@MainActor修饰的闭包会强制在主线程执行,既满足@Sendable的跨线程安全传递要求,又能合法访问Main Actor隔离的@State属性。
内容的提问来源于stack exchange,提问作者smr
相关产品推荐
相关产品推荐

