我有一个调用Firestore抓取一些数据并存储到
@published var userJournals
在另一个视图中,我去调用变量,它是空的。我检查了从firestore初始拉取的数据,数据显示和映射成功。想知道我做错了什么在另一个视图。
视图1
class JournalDashLogic: ObservableObject {
@Published var userJournals = [UserJournalEntry]()
@Published var userJournalIDs = [String]()
func grabUserJournals(journalID: String) {
//grab current user
guard let uid = FirebaseManager.shared.auth.currentUser?.uid else {
return
}
FirebaseManager.shared.firestore
.collection("users")
.document(uid)
.collection("userJournalEntrys")
.document(journalID)
.collection("items")
.addSnapshotListener { (snapshot, err) in
guard let documents = snapshot?.documents else {
print("no documents present")
return
}
//map to journal entry struct
self.userJournals = documents.map { (querySnapshot) -> UserJournalEntry in
let data = querySnapshot.data()
let dateCreated = data["dateCreated"] as? String ?? ""
let dayOfWeek = data["dayOfWeek"] as? String ?? ""
let mealCalories = data["mealCalories"] as? Int ?? 0
let mealCarbs = data["mealCarbs"] as? Int ?? 0
let mealFat = data["mealFat"] as? Int ?? 0
let mealName = data["mealName"] as? String ?? ""
let mealProtein = data["mealProtein"] as? Int ?? 0
let MealServing = data["MealServing"] as? Int ?? 0
let mealSaved = data["saved"] as? Bool ?? false
let mealTiming = data["timeCreated"] as? String ?? ""
let entry = UserJournalEntry(
id: UUID().uuidString, mealName: mealName, mealFat: mealFat, mealCarbs: mealCarbs,
mealProtein: mealProtein, mealCalories: mealCalories, MealServing: MealServing,
mealSaved: mealSaved, mealTiming: mealTiming, dayOfWeek: dayOfWeek,
totalCalories: "100", dateCreated: dateCreated)
return entry
}
}
}
}
视图2
.onAppear {
for id in jm.userJournalIDs {
jm.grabUserJournals(journalID: id)
}
}
显示自视图2
.sheet(isPresented: $showAllJournals) {
SavedJournalsList(savedJournalIDs: jm.userJournalIDs, savedJournals: jm.userJournals)
.transition(transition)
}
3视图struct SavedJournalsList: View {
@State var savedJournalIDs: [String]
@State var savedJournals: [UserJournalEntry]
var body: some View {
VStack(alignment: .leading) {
ForEach(savedJournals, id: .self) { entry in
HStack {
Text(entry.dateCreated).bold()
Text("Total Calories: 3200")
.padding(.leading, 15)
}
.frame(maxWidth: .infinity)
.multilineTextAlignment(.center)
HStack {
Text("200 Carbs")
.foregroundColor(.gray)
Text("250 Protein")
.foregroundColor(.gray)
Text("100 Fat")
.foregroundColor(.gray)
}
.padding(.all, 5)
.frame(maxWidth: .infinity)
}
.frame(width: 300, height: 100)
.background(.white)
.cornerRadius(15)
.shadow(color: Color("LighterGray"), radius: 5, x: 0, y: 8)
}
}
}
struct SavedJournalsList: View {
@State var savedJournalIDs: [String]
@State var savedJournals: [UserJournalEntry]
var body: some View {
VStack(alignment: .leading) {
ForEach(savedJournals, id: .self) { entry in
HStack {
Text(entry.dateCreated).bold()
Text("Total Calories: 3200")
.padding(.leading, 15)
}
.frame(maxWidth: .infinity)
.multilineTextAlignment(.center)
HStack {
Text("200 Carbs")
.foregroundColor(.gray)
Text("250 Protein")
.foregroundColor(.gray)
Text("100 Fat")
.foregroundColor(.gray)
}
.padding(.all, 5)
.frame(maxWidth: .infinity)
}
.frame(width: 300, height: 100)
.background(.white)
.cornerRadius(15)
.shadow(color: Color("LighterGray"), radius: 5, x: 0, y: 8)
}
}
}
你可以试试我为我的项目创建的这个函数
func lisentDocument<T:Codable>(docPath: String, model: T.Type, completion:@escaping(T?,String?) -> Void) -> ListenerRegistration? {
let docRef = db.document(docPath)
var listner: ListenerRegistration? = nil
listner = docRef.addSnapshotListener { response, error in
if error != nil {
completion(nil, error?.localizedDescription)
print(listner)
}
do {
let data = try response?.data(as: model)
completion(data, nil)
} catch {
completion(nil, FBError.someThingWentWrong.message)
}
}
return listner
}
如何使用
lisentDocument(docPath: "Doc Path", model: [UserJournalEntry].self,
completion: { data, error in
self.userJournals = data
})
如果你有Object作为响应使用可以使用模型作为UserJournalEntry.self
注意事项:
-
MealServing
是大写的,我觉得应该是小写的:mealServing
-
不需要手动映射数据,而是使用Codable。参见官方文档
-
你正在使用视图模型,所以不需要在你的视图上使用
@State
属性。请使用视图模型。 -
你在你的视图模型中的id上迭代,看起来你正在尝试为每个这些文档设置一个快照监听器。这是低效的,您应该在集合(或查询)上设置侦听器,然后将其结果分配给已发布的属性
userJournals
。文档中有一个示例展示了如何做到这一点。如果您对代码示例感兴趣,请查看repo