在 NavigationView 中加载视图的标准方法是啥,每个视图都拥有一个从 API 填充的模型?
Posted
技术标签:
【中文标题】在 NavigationView 中加载视图的标准方法是啥,每个视图都拥有一个从 API 填充的模型?【英文标题】:What's the Standard Way of Loading Views in a NavigationView where each Owns a Model that's Populated from an API?在 NavigationView 中加载视图的标准方法是什么,每个视图都拥有一个从 API 填充的模型? 【发布时间】:2020-10-16 13:35:01 【问题描述】:我有 2 个视图:A 和 B。视图 A 有一个从 API 端点加载其数据的模型,视图 B 也是如此。
视图 A 有一个按钮,单击该按钮后会将视图 B 推入堆栈。这是执行此操作的代码:
应用:
import SwiftUI
@main
struct TempApp: App
var body: some Scene
WindowGroup
ViewA()
视图/模型 A:
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()
模型/视图 B:
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 的代码会立即(在 NavigationLink 调用中)实例化视图 B,因此模型 B 会进行网络调用以加载它的数据,这会导致错误:
更新耗时超过 5 秒
即使我延迟加载数据,上面的示例应用也能正常预览,所以我不知道为什么!
【问题讨论】:
【参考方案1】: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")
【讨论】:
非常感谢您的提示!我不确定我是否 100% 理解了预览提示,但我会在今天晚些时候尝试这样做,并会告诉你进展如何。 实际上将模型更改为StateObject
而不是您建议的ObservedObject
解决了我遇到的预览问题!再次感谢。以上是关于在 NavigationView 中加载视图的标准方法是啥,每个视图都拥有一个从 API 填充的模型?的主要内容,如果未能解决你的问题,请参考以下文章