Mapping firestore documents in swift with codable using a function in a class

Viewed 76

I am trying to map firestore documents using Codable in swift. I have tried writing functions that seem to throw up errors. I have now written one that has no errors however the function is within a class. I think this is causing problems

Here is the code for the class & function:

import SwiftUI
import Firebase
import FirebaseFirestoreSwift

class FetchUserVM: ObservableObject {

    @Published var user = [UserModel]()
    
    private var db = Firestore.firestore()

  
    
    func fetchUser() {
    
    db.collection("Users").addSnapshotListener { (querySnapshot, error) in
        
        guard let documents = querySnapshot?.documents else {
            
            print("No Documents")
            return
            
        }
        
        self.user = documents.compactMap { (queryDocumentSnapshot) -> UserModel? in
            
            return try? queryDocumentSnapshot.data(as: UserModel.self)
            
        }
    }
}
    
    
}

Here is where I am using the fetchUser function. (ProfileViewModel which is a class)

import SwiftUI
import Firebase

class ProfileViewModel : ObservableObject {
    
    @EnvironmentObject var sharedData: SharedDataModel
    
    @Published var userInfo = UserModel(username: "", pic: "", bio: "", uid: "")
    @AppStorage("current_status") var log_Status = false
    
    @Published var picker = false
    @Published var img_data = Data(count: 0)
    
    @Published var isLoading = false
    

    let ref = Firestore.firestore()
    let uid = Auth.auth().currentUser!.uid
    

    init() {

        fetchUser(uid: uid) { (user) in
            self.userInfo = user
        }
    }

    func logOut(){
        
        // logging out..
        
        try! Auth.auth().signOut()
        log_Status = false
    }
    
    func updateImage(){
        
        isLoading = true
        
        UploadImage(imageData: img_data, path: "profile_Photos") { (url) in
            
            self.ref.collection("Users").document(self.uid).updateData([
            
                "imageurl": url,
            ]) { (err) in
                if err != nil{return}
                
                // Updating View..
                self.isLoading = false
                fetchUser(uid: self.uid) { (user) in
                    self.userInfo = user
                }
            }
        }
    }
    
    func updateDetails(field : String){
        
        alertView(msg: "Update \(field)") { (txt) in
            
            if txt != ""{
                
                self.updateBio(id: field == "Name" ? "username" : "bio", value: txt)
            }
        }
    }
    
    func updateBio(id: String,value: String){
        
        ref.collection("Users").document(uid).updateData([
        
            id: value,
        ]) { (err) in
            
            if err != nil{return}
            
            // refreshing View...
            
            fetchUser(uid: self.uid) { (user) in
                self.userInfo = user
            }
        }
    }
}

When i call the fetchUser function, i get the error:

'Cannot find fetchUser in scope'

What is the way around this?

EDITED: I have since changed my fetchUser function. The fetchUser function i had before worked however it was mapping manually which is less than ideal!

Here is the original fetchUser function for this project:

let ref = Firestore.firestore()

func fetchUser(uid: String,completion: @escaping (UserModel) -> ()){

    //MARK: Have not tested the following lines...
    let db = Firestore.firestore()
    @EnvironmentObject var sharedData: SharedDataModel

    ref.collection("Users").document(uid).getDocument { (doc, err) in
        guard let user = doc else{return}

        let username = user.data()?["username"] as? String ?? "No Username"
        let pic = user.data()?["imageurl"] as? String ?? "No image URL"
        let bio = user.data()?["bio"] as? String ?? "No bio"
        let uid = user.data()?["uid"] as? String ?? ""
        let isVerified = user.data()?["isVerified"] as? Bool ?? false


        DispatchQueue.main.async {
            completion(UserModel(username: username, pic: pic, bio: bio, uid: uid, isVerified: isVerified))
        }
    }
}


This is what i have changed it to (am getting 'Cannot find self in scope errors):

func fetchUser(documentId: String) {
    let db = Firestore.firestore()
    
  let docRef = db.collection("Users").document(documentId)

  docRef.getDocument { document, error in
    if let error = error as NSError? {
      self.errorMessage = "Error getting document: \(error.localizedDescription)"
    }
    else {
      if let document = document {
        do {
          self.user = try document.data(as: UserModel.self)
        }
        catch {
          print(error)
        }
      }
    }
  }
}

There is something i am not doing here but everywhere i look i can't find the solution.

0 Answers
Related