'How to grab the current users "firstname" from firebase store. Swift 5

I did more trial and error and a bit of online research and this is what I came back with:

func presentWelcomeMessage() {
    
               //Get specific document from current user
               let docRef = Firestore.firestore()
                  .collection("users")
                  .whereField("uid", isEqualTo: Auth.auth().currentUser?.uid ?? "")

               // Get data
               docRef.getDocuments { (querySnapshot, err) in
                   if let err = err {
                       print(err.localizedDescription)
                   } else if querySnapshot!.documents.count != 1 {
                       print("More than one document or none")
                   } else {
                       let document = querySnapshot!.documents.first
                       let dataDescription = document?.data()
                       guard let firstname = dataDescription?["firstname"] else { return }
                       self.welcomeLabel.text = "Hey, \(firstname) welcome!"
                   }
               }

It works, but am not sure if it is the most optimal solution.



Solution 1:[1]

First I should say firstname is not really the best way to store a var. I would recommend using firstName instead for readability. I also recommend getting single documents like I am, rather than using a whereField.

An important thing to note is you should create a data model like I have that can hold all of the information you get.

Here is a full structure of how I would get the data, display it, and hold it.

struct UserModel: Identifiable, Codable {
    var id: String
    var firstName: String

    private enum CodingKeys: String, CodingKey {
       case id
       case firstName
    }
}
import SwiftUI
import FirebaseAuth
import FirebaseFirestore
import FirebaseFirestoreSwift

class UserDataManager: ObservableObject {
    private lazy var authRef = Auth.auth()
    private lazy var userInfoCollection = Firestore.firestore().collection("users")
    
    public func getCurrentUIDData(completion: @escaping (_ currentUserData: UserModel) -> Void) {
        if let currentUID = self.authRef.currentUser?.uid {
            self.userInfoCollection.document(currentUID).getDocument { (document, error) in
                if let document = document {
                    if let userData = try? document.data(as: UserModel.self) {
                        completion(userData)
                    }
                } else if let error = error {
                    print("Error getting current UID data: \(error)")
                }
            }
        } else {
            print("No current UID")
        }
    }
}
struct ContentView: View {
    @State private var userData: UserModel? = nil
    private let
    var body: some View {
        ZStack {
            if let userData = self.userData { <-- safely unwrap data
                Text("Hey, \(userData.firstName) welcome!")
            }
        }
        .onAppear {
            if self.userData == nil { <-- onAppear can call more than once
                self.udm.getCurrentUIDData { userData in
                   self.userData = userData  <-- pass data from func to view
                }
            }
        }
    }
}

Hopefully this can point you in a better direction of how you should be getting and displaying data. Let me know if you have any further questions or issues.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Jay