mvvm - SwiftUI - 如何将日期字符串从日期选择器传回查看模型
问题描述
我想要完成的事情
我有一个代表日期选择器的视图和另一个代表特定日期的锻炼课程列表的视图。当用户更改日期选择器视图中的日期时,我想更新锻炼列表。我正在遵循 MVVM 设计,我基本上希望在我的视图模型中保持状态(日期字符串和与该日期有关的锻炼列表)并将其传递给我的视图。
stateDate
当用户通过日期选择器选择一个新日期并让它在另一个视图中填充该字符串时,我想首先在我的视图模型中更新我的变量。最终目标是更新我从中提取数据的 Firestore 中的路径,以便我可以提取新数据。
当用户在我的一个视图中通过日期选择器选择新日期时,如何更新视图模型中的 @Published 变量?
源代码段
锻炼日期选择器视图
import SwiftUI
struct WorkoutDatePicker: View {
@ObservedObject var viewModel = WorkoutClassViewModel()
var body: some View {
Form {
DatePicker("Date",
selection: $viewModel.stateDate,
displayedComponents: [.date])
Text("Your current date is \(viewModel.stateDate)")
}
}
}
WorkoutClassViewModel 视图模型
import Foundation
import FirebaseFirestore
class WorkoutClassViewModel: ObservableObject {
@Published var workoutClasses = [WorkoutClass]()
@Published var stateDate = Date()
private var db = Firestore.firestore()
func fetchData() {
// let dateString = getDateString(date: userData.date,format: "MM-dd-YYYY")
// db.collection("schedules/\(dateString)/classes").addSnapshotListener { (querySnapshot, error) in
db.collection("schedules/2021-07-18/classes").addSnapshotListener { (querySnapshot, error) in
guard let documents = querySnapshot?.documents else {
print("No documents")
return
}
self.workoutClasses = documents.map { (queryDocumentSnapshot) -> WorkoutClass in
let data = queryDocumentSnapshot.data()
let id = queryDocumentSnapshot.documentID
let reservationCnt = data["reservationCnt"] as? Int ?? 0
let workoutType = data["workoutType"] as? String ?? ""
return WorkoutClass(id: id, reservationCnt: reservationCnt, workoutType: workoutType)
}
}
}
}
类视图视图
import SwiftUI
struct ClassView: View {
@ObservedObject var viewModel = WorkoutClassViewModel()
var body: some View {
VStack{
WorkoutDatePicker()
NavigationView {
List(viewModel.workoutClasses) { workoutClass in
VStack(alignment: .leading) {
Text(workoutClass.workoutType).font(.title)
}
}.onAppear() {
self.viewModel.fetchData()
}
}
}
}
}
我是 SwiftUI 和 iOS 开发的新手,所以任何建议都是好建议!
解决方案
现在,您有两个不同的WorkoutClassViewModel
. 当一个更新时,另一个不知道日期已更改。为了解决这个问题,您可以WorkoutClassViewModel
通过传递对子视图 ( WorkoutDatePicker
) 的引用来共享相同的内容。这在这个问题的另一个答案中得到了说明。
另一种选择是将子视图的职责与仅选择日期分开,将 a 传递@Binding
给子视图可以使用的:stateDate
struct WorkoutDatePicker: View {
@Binding var date : Date //<-- Here
var body: some View {
Form {
DatePicker("Date",
selection: $date,
displayedComponents: [.date])
Text("Your current date is \(date)")
}
}
}
struct ClassView: View {
@StateObject private var viewModel = WorkoutClassViewModel() //<-- Here
var body: some View {
VStack{
WorkoutDatePicker(date: $viewModel.stateDate)
Text("Date: \(viewModel.stateDate)")
NavigationView {
List(viewModel.workoutClasses) { workoutClass in
VStack(alignment: .leading) {
Text(workoutClass.workoutType).font(.title)
}
}.onAppear() {
self.viewModel.fetchData()
}
}
}
}
}
推荐阅读
- matlab - 如何在 MATLAB 中翻转 NIFTI 图像 (.nii)?
- github - 在 Windows 图像的 GitHub 操作下通过 Chocolatey 安装后无法使用 ImageMagick
- css - Jupyter书中数学的大小格式
- c# - 如何保护 .Net/C# 应用程序的 Oracle 连接?
- monaco-editor - 无法读取未定义的属性“getStart”
- javascript - 'else' 不适用于 eventListener
- node.js - 如何在 node.js 中反序列化 avro 模式消息
- bash - 收到错误“没有这样的文件或目录”
- linux - 增量文件的 Bash 循环脚本
- python - Pandas:根据另一列过滤 groupby 重复的行