在 NavigationView 中加载视图的标准方法是什么,其中每个视图都拥有一个从 API 填充的模型?

What's the Standard Way of Loading Views in a NavigationView where each Owns a Model that's Populated from an API?

我有 2 个视图:A 和 B。视图 A 有一个从 API 端点加载数据的模型,视图 B 也是如此。

视图 A 有一个按钮,单击该按钮会将视图 B 推入堆栈。这是执行此操作的代码:

应用程序:

import SwiftUI

@main
struct TempApp: App {
    var body: some Scene {
        WindowGroup {
            ViewA()
        }
    }
}

View/Model答:

import SwiftUI

let REQUEST_DELAY = 6.0 // to simulate(ish) a network request

struct ViewA: View {
    @ObservedObject var model: ViewAModel = ViewAModel()
    @State var shouldGoToNextView = false
    
    var body: some View {
        NavigationView {
            if (self.model.isLoaded) {
                VStack {
                    Text(self.model.data)
                        .font(.title)
                    NavigationLink(destination: ViewB(), isActive:$shouldGoToNextView) {
                        EmptyView()
                    }
                    Button(action: {self.shouldGoToNextView=true}) {
                        Text("GO")
                            .font(.headline)
                            .foregroundColor(.white)
                            .padding()
                            .frame(width: 220, height: 60)
                            .background(Color.blue)
                            .cornerRadius(15.0)
                    }
                }
            } else {
                Text("Not ready...")
                    .font(.title)
            }
        }
        .onAppear(perform: {
            self.shouldGoToNextView = false
        })
    }
}

class ViewAModel : ObservableObject {
    var data: String = ""
    @Published var isLoaded : Bool = false
    
    init() {
        // simulate getting the data from the network
        DispatchQueue.main.asyncAfter(deadline: .now() + REQUEST_DELAY) {
            // your code here
            self.data = "All loaded fine.."
            self.isLoaded = true
        }
    }
}

struct ViewA_Previews: PreviewProvider {
    static var previews: some View {
        ViewA()
    }
}

Model/View乙:

import SwiftUI

struct ViewB: View {
    @ObservedObject var model: ViewBModel = ViewBModel()
    var body: some View {
        if (self.model.isLoaded) {
            Text(self.model.data)
                .font(.title)
        } else {
            Text("Secondary data not ready...")
                .font(.title)
        }
    }
}

class ViewBModel: ObservableObject {
    var data: String = ""
    @Published var isLoaded: Bool = false
    
    init() {
        // simulate getting the data from the network
        DispatchQueue.main.asyncAfter(deadline: .now() + REQUEST_DELAY) {
            self.data = "Secondary model data loaded fine.."
            self.isLoaded = true
        }
    }
}

struct ViewB_Previews: PreviewProvider {
    static var previews: some View {
        ViewB()
    }
}

此代码在 运行 时有效,但我有 1 个问题和 1 个问题:

问题:这是在SwiftUI中实现上述目标的最佳方式吗?具体来说,我不确定我使用 State/ObservedObject 以及 NavigationLink 和 Button 的组合来导航到另一个视图。

问题: 我无法在我正在处理的真实应用程序中预览视图 A,因为视图 ​​A 的代码会立即实例化视图 B(在 NavigationLink 调用中),因此模型 B 使加载其数据的网络调用,并导致错误:

Updating took more than 5 seconds

尽管我延迟加载数据,但上面的示例应用程序预览效果很好,所以我不确定为什么!

1- 要转到视图 B,使用此代码更容易:

        NavigationLink(destination: ViewB()) {
            Text("Your buttons text")
        }

2- 你应该使用 StateObject.

而不是 ObservedObject

3- 不用 isLoaded,您只需 @Published 您的 data.

4- 为了能够预览这些,我建议您将它们包装在容器视图中,您可以在其中传递其依赖项,在本例中 data 是一个字符串。例如:

struct A: View {
   var viewModel = ViewModel()
   var body: some View {
        if !data.isEmpty {
          ABodyView(data: data)
        }
    }

 }

struct ABodyView: View {
     let data: String 
      var body: some View {
         Text(data)
      }
}

struct ABodyView_Previews: PreviewProvider {
    static let previews: some View {
        ABodyView(data: "whatever you want")
     }
}