Jam*_*mes 5 swiftui property-wrapper-published ios17 macos-sonoma
我一直在尝试使用onKeyPress
SwiftUI 5 中的新功能。但是,更新到@Published
在处理程序中更新可观察对象的属性会产生警告“不允许从视图更新中发布更改,这将导致未定义的行为。”
注意,在实践中我还没有看到任何实际错误,但 Xcode 在控制台中记录了大量红色警告和紫色运行时问题。
简单的复制;可以通过按钮修改,也可以在本地修改@State
而不提示;但是,修改该@Published
属性会onKeyPress
产生警告。
import SwiftUI
@MainActor
class ExampleService: ObservableObject {
@Published var text = ""
}
struct ContentView: View {
@StateObject var service = ExampleService()
@State var localText = ""
var body: some View {
VStack {
Button {
// This is fine
service.text += "!"
} label: {
Text("Press Me")
}
Label("Example Focusable", systemImage: "arrow.right")
.focusable()
.onKeyPress { action in
// XCode whines about "Publishing changes from within view updates is not allowed, this will cause undefined behavior."
service.text += "."
return .handled
}
Label("Example Local State", systemImage: "arrow.left")
.focusable()
.onKeyPress { action in
// This is fine
localText += "."
return .handled
}
Text(service.text)
Text(localText)
}
}
}
#Preview {
ContentView()
}
Run Code Online (Sandbox Code Playgroud)
要使警告消失,请使用
DispatchQueue.main.async {
service.text += "."
}
Run Code Online (Sandbox Code Playgroud)
这将确保按照 SwiftUI 的要求在主线程上执行 UI 更新。请注意,正如评论中提到的,您也可以使用Task{...}
.
据我了解,@MainActor
应该在主队列上执行,但(我猜)并不总是如此。请参阅此提案以将其从 Swift 6 中删除:
https://github.com/apple/swift-evolution/blob/main/proposals/0401-remove-property-wrapper-isolation.md