rest - SwiftUI:如何更新 NavigationView 详细信息屏幕?
问题描述
我有一个从 REST 后端服务器获取车辆列表的应用程序。然后,它使用该列表来构建一个车辆列表,可以点击这些车辆来显示其中一辆的详细信息:
@State private var selectedVehicle: Vehicle?
@Binding var vehicles: [Vehicle]
List {
NavigationView {
ForEach( vehicles ) { vehicle in
NavigationLink( destination: VehicleDetailScreen( vehicle: vehicle ),
tag: vehicle,
selection: self.$selectedVehicle ) {
Text( vehicle.name )
}
}
}
}
struct VehicleDetailScreen: View {
var vehicle: Vehicle
var body: some View {
// Lots of rendering code omitted
}
}
到目前为止,一切都很好。这很好用。当我们从服务器获取更新的信息时,问题就出现了。更新绑定vehicles
属性非常适合更新列表。但详细信息屏幕仍显示不再相关的数据。
我的第一个想法就是从 NavigationView 中弹出详细视图。不幸的是,SwiftUI 没有提供任何可靠的方法,我可以找到在 iPad 上的两列视图中执行此操作。
我的下一个想法是,我们也需要将车辆作为 @Binding 传递给 VehicleDetailScreen,以便我们可以更新它。但这也很难做到,因为我们需要对该绑定的引用,以便我们可以将更新的值填入其中。我能想到的唯一方法是完全重写我们的网络和模型对象代码,使其像 CoreData 一样工作,将对象保存在内存中并使用来自服务器的新值更新它们,而不是生成新对象。这将是一个很大的努力,如果有其他选择,显然不是我热衷于做的事情。
所以我有点坚持这一点。非常欢迎任何想法/想法/建议!
解决方案
如果您希望在数据更改时更新详细视图,则必须使用绑定。
就架构而言,我建议创建所谓的存储,以保存可在多个视图中使用的数据。这与 Stores 的一些静态提供程序相结合,使您可以在任何地方轻松访问和修改数据,并让您的视图自动更新。
使用 UIKit 时,您将通过调用reloadTable
例如手动刷新数据。在 SwiftUI 中,这还没有完成。您可以假设手动触发要更新的视图,但我建议不要这样做,因为这不是 SwiftUI 的预期方式。
我已经修改了您的代码以显示一个示例:
class StoreProvider {
static let carStore = CarStore()
}
class CarStore: ObservableObject {
@Published var vehicles: [Vehicle] = [Vehicle(id: "car01", name: "Porsche", year: 2016), Vehicle(id: "car02", name: "Lamborghini", year: 2002)]
}
struct Vehicle: Identifiable, Hashable {
let id: String
var name: String
var year: Int
}
struct CarOverview: View {
@ObservedObject var store = StoreProvider.carStore
@State var selectedVehicle: Vehicle?
var body: some View {
NavigationView {
List {
ForEach(store.vehicles.indices) { vehicleIndex in
NavigationLink(destination: VehicleDetailScreen(vehicle: self.$store.vehicles[vehicleIndex])) {
Text(self.store.vehicles[vehicleIndex].name)
}.onTapGesture {
self.selectedVehicle = self.store.vehicles[vehicleIndex]
}
}
}
}
}
}
struct VehicleDetailScreen: View {
@Binding var vehicle: Vehicle
func updateValues() {
vehicle.year = Int.random(in: 1990..<2020)
}
var body: some View {
VStack {
Text(vehicle.name)
Text("Year: ") + Text(vehicle.year.description)
}.onTapGesture(perform: updateValues)
}
}
推荐阅读
- angular - Angular - 在我的组件中处理一个通用字典,我使用 HTTPClient 作为 HTTP 请求的响应返回
- python - 无法更改语言以获得所需的输出
- ruby-on-rails - 新的 Ruby on Rails 应用程序(不识别 Gemfile)
- docker - 将文件复制到 LCOW 中的 docker 映像
- android - 将图像信息从 Unity 传递到 Android 以使用 MLKit
- android - 在 notifyItemInserted 后 RecyclerView 不更新视图
- java - 字符串特殊字符
- java - 在 GridView 中重复的图像
- ruby - erubis: `scan': US-ASCII 中的无效字节序列 (ArgumentError)
- java - java.lang.ClassNotFoundException sun.misc.GC