简体   繁体   English

视图中的 Firestore 方法 model 未在 SwiftUI onAppear 方法中调用

[英]Firestore method in view model not invoking in SwiftUI onAppear method

I want to implement a Text field that displays the current user's existing score in the DB (Firestore).我想实现一个文本字段来显示当前用户在数据库(Firestore)中的现有分数。 Because of the nature of async in Firebase query, I also need to do some adjustment in my codes.由于 Firebase 查询中异步的性质,我还需要对我的代码进行一些调整。 However, it seems that completion() handler does not work well:但是, completion()处理程序似乎无法正常工作:

// ViewModel.swift

import Foundation
import Firebase
import FirebaseFirestore

class UserViewModel: ObservableObject {
    let current_user_id = Auth.auth().currentUser!.uid
    private var db = Firestore.firestore()
    @Published var xp:Int?
    
    func fetchData(completion: @escaping () -> Void) {
        let docRef = db.collection("users").document(current_user_id)
        
        docRef.getDocument { snapshot, error in
              print(error ?? "No error.")
              self.xp = 0
              guard let snapshot = snapshot else {
                  completion()
                  return
              }
            self.xp = (snapshot.data()!["xp"] as! Int)
            completion()
        }
    }
}
// View.swift

import SwiftUI
import CoreData
import Firebase

{
    @ObservedObject private var users = UserViewModel()
    var body: some View {
        VStack {
            HStack {
                // ...
                Text("xp: \(users.xp ?? 0)")
//                    Text("xp: 1500")
                    .fontWeight(.bold)
                    .padding(.horizontal)
                    .foregroundColor(Color.white)
                    .background(Color("Black"))
                    .clipShape(CustomCorner(corners: [.bottomLeft, .bottomRight, .topRight, .topLeft], size: 3))
                    .padding(.trailing)
            }
            .padding(.top)
            .onAppear() {
                self.users.fetchData()
            }
// ...
    }
}

My result kept showing 0 in Text("xp: \(users.xp?? 0)") , which represents that the step is yet to be async'ed.我的结果在Text("xp: \(users.xp?? 0)")中一直显示 0,这表示该步骤尚未异步。 So what can I do to resolve it?那么我能做些什么来解决它呢?

I would first check to make sure the data is valid in the Firestore console before debugging further.在进一步调试之前,我会首先检查以确保 Firestore 控制台中的数据有效。 That said, you can do away with the completion handler if you're using observable objects and you should unwrap the data safely.也就是说,如果您使用可观察对象,则可以取消完成处理程序,并且应该安全地解包数据。 Errors can always happen over network calls so always safely unwrap anything that comes across them.错误总是可以通过网络调用发生,所以总是安全地解开遇到的任何东西。 Also, make use of the idiomatic get() method in the Firestore API, it makes code easier to read.此外,利用 Firestore API 中惯用的get()方法,它使代码更易于阅读。

That also said, the problem is your call to fetch data manually in the horizontal stack's onAppear method.也就是说,问题在于您调用水平堆栈的onAppear方法手动获取数据。 This pattern can produce unsavory results in SwiftUI, so simply remove the call to manually fetch data in the view and perform it automatically in the view model's initializer.这种模式可能会在 SwiftUI 中产生令人讨厌的结果,因此只需删除在视图中手动获取数据的调用并在视图模型的初始化程序中自动执行它。

class UserViewModel: ObservableObject {
    @Published var xp: Int?
    
    init() {
        guard let uid = Auth.auth().currentUser?.uid else {
            return
        }
        let docRef = Firestore.firestore().collection("users").document(uid)

        docRef.getDocument { (snapshot, error) in
            if let doc = snapshot,
               let xp = doc.get("xp") as? Int {
                self.xp = xp
            } else if let error = error {
                print(error)
            }
        }
    }
}

struct ContentView: View {
    @ObservedObject var users = UserViewModel()

    var body: some View {
        VStack {
            HStack {
                Text("xp: \(users.xp ?? 0)")
            }
        }
    }
}

SwiftUI View - viewDidLoad()? SwiftUI 查看 - viewDidLoad()? is the problem you ultimately want to solve.是你最终想要解决的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM