下面的视图在 Xcode 16.1 中正常工作。在 Xcode 16.2 beta 2 中构建,您会在闭包中收到以下错误onPreferenceChange
:“主参与者隔离属性‘height’无法从 Sendable 闭包中变异”。(Swift 6 语言模式)。
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)")
}
}
}
查看 Xcode 16.1 中的签名onPreferenceChange
:
@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 中:
@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
不同之处在于@Sendable
在闭包中添加了。不幸的是,他们也没有这样做,@MainActor
所以你无法更新包含View
的属性。只是为了好玩,我将任务包装在了中Task
,但这会导致崩溃(“EXC_BAD_ACCESS code=2”):
.onPreferenceChange(HeightKey.self) { height in
Task { @MainActor in
self.height = height
}
}
onPreferenceChange
不回到 Swift 5 模式我们该如何使用?
您可以通过将所有内容包装在 MainActor.assumeIsolated 中来解决这个问题:
只要从主线程调用,这应该没问题。