在 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")
}
}
我有 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")
}
}