繁体   English   中英

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

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

我想实现一个文本字段来显示当前用户在数据库(Firestore)中的现有分数。 由于 Firebase 查询中异步的性质,我还需要对我的代码进行一些调整。 但是, 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()
            }
// ...
    }
}

我的结果在Text("xp: \(users.xp?? 0)")中一直显示 0,这表示该步骤尚未异步。 那么我能做些什么来解决它呢?

在进一步调试之前,我会首先检查以确保 Firestore 控制台中的数据有效。 也就是说,如果您使用可观察对象,则可以取消完成处理程序,并且应该安全地解包数据。 错误总是可以通过网络调用发生,所以总是安全地解开遇到的任何东西。 此外,利用 Firestore API 中惯用的get()方法,它使代码更易于阅读。

也就是说,问题在于您调用水平堆栈的onAppear方法手动获取数据。 这种模式可能会在 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 查看 - viewDidLoad()? 是你最终想要解决的问题。

暂无
暂无

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

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