简体   繁体   English

从 Firebase 具有特定 ID 的文档中提取时,表达式类型不明确,没有更多上下文,映射到 Codable

[英]Error Type of expression is ambiguous without more context when pulling from Firebase Document with specific ID, mapping to Codable

I have a Codable struct called TheUser and im trying to get a firebase document to map to that and continue on with authentication.我有一个名为 TheUser 的 Codable 结构,我正在尝试将 firebase 文档发送到 map 并继续进行身份验证。 I can login to everything fine and when calling the fetchUser func it gives me this error.我可以正常登录一切,当调用 fetchUser 函数时,它给了我这个错误。 Note: I copied this code identically to the firebase documentation.注意:我复制了与 firebase 文档相同的代码。

在此处输入图像描述

Here is the code for the func这是函数的代码

    func fetchUser(uid: String) {
        db.collection("users").getDocument { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No User Profile Found")
                return
            }
            
            self.theuser = documents.compactMap { (queryDocumentSnapshot) -> TheUser? in
                try? queryDocumentSnapshot.data(as: TheUser.self)
            }
        }
    }

Here is the code for the entire ViewModel (ignore the // Im still debugging)这是整个 ViewModel 的代码(忽略 // 我还在调试)

import SwiftUI
import Firebase
import FirebaseFirestoreSwift

class AuthViewModel: ObservableObject {
    @Published var userSession: Firebase.User?
    @Published var didAuthenticateUser = false
    @Published var accountWasFound = false
    @Published var currentUser: User?
    @Published var theuser = [TheUser]()
    private var tempUserSession: Firebase.User?
    
    private let service = UserService()
    private var db = Firestore.firestore()
        
    init() {
        self.userSession = Auth.auth().currentUser
        //self.fetchUser()
    }
    
    func checkEmail(email: String) {
        Auth.auth().fetchSignInMethods(forEmail: email, completion: {
                (e, error) in

                if let error = error {
                    print(error.localizedDescription)
                } else if e != nil {
                    self.accountWasFound.toggle()
                    print("Account Was Found")
                }
            })
    }
    
    func login(withEmail email: String, password: String) {
        Auth.auth().signIn(withEmail: email, password: password) { result, error in
            if let error = error {
                print("DEBUG: Failed to sign in with error \(error.localizedDescription)")
                return
            }
            
            guard let user = result?.user else { return }
            self.userSession = user
            self.fetchUser(uid: self.userSession!.uid)
            //self.didAuthenticateUser.toggle()
        }
    }
    
    func fetchUser(uid: String) {
        db.collection("users").getDocument { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No User Profile Found")
                return
            }
            
            self.theuser = documents.compactMap { (queryDocumentSnapshot) -> TheUser? in
                try? queryDocumentSnapshot.data(as: TheUser.self)
            }
        }
    }
    
    func register(withEmail email: String, password: String, fullname: String, username: String) {
        Auth.auth().createUser(withEmail: email, password: password) { result, error in
            if let error = error {
                print("DEBUG: Failed to register with error \(error.localizedDescription)")
                return
            }
            
            guard let user = result?.user else { return }
            self.tempUserSession = user
            
            let data = ["email": email,
                        "username": username.lowercased(),
                        "fullname": fullname,
                        "uid": user.uid]
            
            Firestore.firestore().collection("users")
                .document(user.uid)
                .setData(data) { _ in
                    self.didAuthenticateUser = true
                }
        }
    }
    
    func signOut() {
        // sets user session to nil so we show login view
        userSession = nil
        
        // signs user out on server
        try? Auth.auth().signOut()
    }
    
    /*
    func uploadProfileImage(_ image: UIImage) {
        guard let uid = tempUserSession?.uid else { return }
        
        ImageUploader.uploadImage(image: image) { profilePictureUrl in
            Firestore.firestore().collection("users")
                .document(uid)
                .updateData(["profilePictureUrl": profilePictureUrl]) { _ in
                    self.userSession = self.tempUserSession
                    self.fetchUser()
                }
        }
    }
    
    func persistImageToStorage() {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        let ref = Storage.storage().reference(withPath: "/profile_image/profile_\(uid)")
        guard let imageData = self.image?.jpegData(compressionQuality: 0.5) else { return }
        ref.putData(imageData, metadata: nil) { metadata, err in
            if let err = err {
                self.StatusMessage = "Failed to push image to Storage: \(err)"
                return
            }
            
            ref.downloadURL { url, err in
                if let err = err {
                    self.StatusMessage = "Failed to retrieve downloadURL: \(err)"
                    return
                }
                self.profilePictureURL = url?.absoluteString ?? ""
                self.StatusMessage = "Successfully stored image with url: \(url?.absoluteString ?? "")"
                Firestore.firestore().collection("users")
                    .document(self.userSession?.uid ?? "")
                    .updateData(["profilePictureURL": self.profilePictureURL]) { _ in
                        print("Uploaded Profile Picture")
                    }
            }
        }
    }
    
    func bannerImageToStorage() {
        guard let uid = Auth.auth().currentUser?.uid else { return }
        let ref = Storage.storage().reference(withPath: "/profile_image/header_\(uid)")
        guard let imageData = self.headerImage?.jpegData(compressionQuality: 0.5) else { return }
        ref.putData(imageData, metadata: nil) { metadata, err in
            if let err = err {
                self.StatusMessage = "Failed to push image to Storage: \(err)"
                return
            }
            
            ref.downloadURL { url, err in
                if let err = err {
                    self.StatusMessage = "Failed to retrieve downloadURL: \(err)"
                    return
                }
                self.headerImageURL = url?.absoluteString ?? ""
                self.StatusMessage = "Successfully stored image with url: \(url?.absoluteString ?? "")"
                Firestore.firestore().collection("users")
                    .document(self.userSession?.uid ?? "")
                    .updateData(["headerPhotoURL": self.headerImageURL]) { _ in
                        print("Banner Uploaded")
                    }
            }
        }
    }
    
    func fetchUser() {
        guard let uid = self.userSession?.uid else { return }
        
        service.fetchUser(withUid: uid) { user in
            self.currentUser = user
        }
    }
     */
}

And here is the code for the Codable struct这是 Codable 结构的代码

import FirebaseFirestoreSwift
import Firebase

struct TheUser: Identifiable, Codable {
    @DocumentID var id: String?
    var username: String
    var phoneNumber: String
    var fullname: String
    var profilePictureURL: String
    var email: String
    var isVerified: Int
    var followers: Int
    var isCurrentUser: Bool
}

I am expecting this to run when called, fetch the data and then login the user.我希望它在调用时运行,获取数据然后登录用户。 The app will then pull from the viewmodel.theuser to full in UI elements on the page and in the app.然后,该应用程序将从 viewmodel.theuser 拉取页面和应用程序中的完整 UI 元素。

The error message is implying the compiler can't infer the type of documents .错误消息暗示编译器无法推断documents的类型。 It's been a while since I've played with Firestore, but iirc correctly getting a snapshot requires the getDocuments (ie the plural) method, not the singular getDocument .自从我玩过 Firestore 以来已经有一段时间了,但是 iirc 正确获取快照需要getDocuments (即复数)方法,而不是单数getDocument

Using the getDocument API call will lead to the the completion handler taking document, error as it's input, not querySnapshot, error , which probably explains why the compiler can't computer what is effectively a type of document.documents .使用getDocument API 调用将导致完成处理程序在输入时获取document, error ,而不是querySnapshot, error ,这可能解释了为什么编译器无法计算实际上是一种类型的document.documents

Change the method call to将方法调用更改为

db.collection("users").getDocuments { (querySnapshot, error) in //...

and see if the compiler is happier.看看编译器是否更快乐。

Note: all from memory, as I don't have a firestore project/database handy to test with...注意:全部来自 memory,因为我没有方便测试的 firestore 项目/数据库...

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

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