无法禁用 SwiftUI View 更新

问题描述 投票:0回答:1

我的应用程序有两种模式:
“运行”模式执行速度非常快,无需任何 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)")
    }
}
swiftui view equality
1个回答
0
投票

您正在使用苹果新的

@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

© www.soinside.com 2019 - 2024. All rights reserved.