我的应用程序有两种模式:
“运行”模式执行速度非常快,无需任何 SwiftUI View 更新,而“单步”模式则需要用户手动推进应用程序状态,并且每一步都需要 View 更新。
在单步模式下,SwiftUI 像往常一样更新我的视图。对于运行模式,我考虑使用这篇文章的建议来禁用自动视图更新。
为了测试该方法,我编写了以下最小项目。
如果我确实正确理解了建议,则
CustomView
不应更新,因为相等函数始终返回 true
。@Observable
final class Model {
var counter = 0
var timer = Timer()
init() {
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
self.counter += 1
}
}
}
@main
struct ViewEquatableApp: App {
let model = Model()
var body: some Scene {
WindowGroup {
CustomView(model: model)
.equatable()
}
}
}
struct CustomView: View, Equatable {
let model: Model
static func == (lhs: CustomView, rhs: CustomView) -> Bool {
// << return yes on view properties which identifies that the
// view is equal and should not be refreshed (ie. `body` is not rebuilt)
true // <- true should disable the View update
}
var body: some View {
ContentView(model: model)
}
}
struct ContentView: View {
let model: Model
var body: some View {
Text("Counter: \(model.counter)")
}
}
您正在使用苹果新的
@Observable
宏,无论您在何处使用它,该宏都会自动为您的类处理视图更新,并且该类中的每个变量都可以被视为 @Published
换句话说,model
中的 CustomView
被视为作为 @ObservedObject
,这样你的视图就会在内部更新,而 Equatable
协议用于避免外部引起的视图更新(例如由父视图)。
因此,在您的情况下,最好为您的类使用传统的
ObservableObject
协议和 @Publsihed
属性,并在需要更新的视图中应用 @ObservedObject
包装器。另外,您不需要使用Equatable
协议
final class Model: ObservableObject {
@Published var counter = 0
var timer = Timer()
init() {
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
self.counter += 1
}
}
}
@main
struct ViewEquatableApp: App {
let model = Model()
var body: some Scene {
WindowGroup {
CustomView(model: model)
}
}
}
struct CustomView: View {
let model: Model
var body: some View {
ContentView(model: model)
}
}
struct ContentView: View {
@ObservedObject var model: Model
var body: some View {
Text("Counter: \(model.counter)")
}
}
这样只有
ContentView
更新,如果你不想更新,请删除其中的@ObservedObject