Mvvm SwiftUI@Binding使用不同的导航项在推送/弹出时重新加载

Mvvm SwiftUI@Binding使用不同的导航项在推送/弹出时重新加载,mvvm,swiftui,Mvvm,Swiftui,我有一个非常简单的应用程序示例,它有两个视图:MasterView和DetailView。主视图显示在带有NavigationView的ContentView中: 导入快捷界面 结构ContentView:View{ var body:一些观点{ 导航视图{ 主视图(视图模型:主视图模型()) .navigationBarTitle(文本(“主控”)) .航海术语( 前导:EditButton() ) } } } 结构主视图:视图{ @观察对象私有var视图模型:主视图模型 初始化(视图模型:主

我有一个非常简单的应用程序示例,它有两个视图:MasterView和DetailView。主视图显示在带有NavigationView的ContentView中:

导入快捷界面
结构ContentView:View{
var body:一些观点{
导航视图{
主视图(视图模型:主视图模型())
.navigationBarTitle(文本(“主控”))
.航海术语(
前导:EditButton()
)
}
}
}
结构主视图:视图{
@观察对象私有var视图模型:主视图模型
初始化(视图模型:主视图模型){
self.viewModel=viewModel
}
var body:一些观点{
打印(“测试”)
返回DataStatusView(数据源:self.$viewModel.result){text->AnyView in
打印(“关闭”)
返回任意视图(列表){
ForEach(text,id:\.self){text in
导航链接(
目标:详细视图(视图模型:详细视图模型(stringToDisplay:text))
) {
文本(文本)
}
}
})
}奥纳佩尔先生{
如果case.waiting=self.viewModel.result{
self.viewModel.fetch()
}
}
}
}
结构详细视图:视图{
@ObservedObject私有var视图模型:DetailViewModel
初始化(viewModel:DetailViewModel){
self.viewModel=viewModel
}
var body:一些观点{
self.showView().onAppear{
self.viewModel.fetch()
}
.navigationBarTitle(文本(“细节”))
}
func showView()->一些视图{
切换self.viewModel.result{
案例。发现(让我们):
返回任意视图(文本)
违约:
返回任意视图(颜色为红色)
}
}
}
DataStatusView是管理某些状态的简单视图:


公共枚举结果状态{
案件等待
装箱
发现个案(T)
案例失败(E)
}
结构数据状态视图:视图,其中内容:视图{
@绑定私有(集合)变量数据源:ResultState
私有出租内容:(T)->content
私人出租等待内容:AnyView?
@Inlineable init(数据源:绑定,
waitingContent:AnyView?=nil,
@ViewBuilder内容:@escaping(T)->content{
self.\u dataSource=数据源
self.waitingContent=waitingContent
self.content=内容
}
var body:一些观点{
self.buildMainView()
}
private func buildMainView()->某些视图{
切换self.dataSource{
案件.等候:
返回任意视图(颜色为红色)
案例.加载:
返回任意视图(颜色为绿色)
发现的案例(let数据):
返回AnyView(self.content(data))
案例。失败:
返回任意视图(颜色为黄色)
}
}
}
视图模型是一个非常简单的“假装打网络电话”虚拟机:

这是“预期的”


处理这个问题的“快捷方式”是什么?显示此问题的示例项目如下:

这是设计问题。SwiftUI基于视图相等,但DataStatusView在每次更新时都会重新创建整个视图层次结构(导航,即更改屏幕,也会调用更新)。所以它破坏了一切。我不知道如何修复它。。。重新思考一下这个概念。好的检查点-完全避免任何视图。谢谢您的评论@Asperi。你有没有一个更好的设计建议?还有一个共同的模式可以避免
AnyView
final class MasterViewModel: ObservableObject {

    @Published var result: ResultState<[String], Error> = .waiting

    init() { }

    func fetch() {
        self.result = .loading
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
            guard let self = self else { return }
            self.result = .found(["This", "is", "a", "test"])
        }
    }
}

final class DetailViewModel: ObservableObject {

    @Published var result: ResultState<String, Error> = .waiting

    private let stringToDisplay: String
    init(stringToDisplay: String) {
        self.stringToDisplay = stringToDisplay
    }

    func fetch() {
        self.result = .loading
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [weak self] in
            guard let self = self else { return }
            self.result = .found(self.stringToDisplay)
        }
    }
}
.navigationBarItems(
                    leading: EditButton()
                )