Kerem Cesme
Kerem Cesme

Reputation: 118

SwiftUI - Show the data fetched from Firebase in view?

Firebase I am trying to show data taken from Firestore in my SwiftUI view but I have a problem. I have no problem with pulling data from Firebase. But I cannot show the data as I want. I work with MVVM architecture.

My model is like this:

struct UserProfileModel: Identifiable {

    @DocumentID var id : String?
    var username : String
    var uidFromFirebase : String
    var firstName : String
    var lastName : String
    var email : String

}

ViewModel:

class UserProfileViewModel: ObservableObject {

    @Published var user : [UserProfileModel] = []

    private var db = Firestore.firestore()

    func data(){
        db.collection("Users").whereField("uuidFromFirebase", isEqualTo: Auth.auth().currentUser!.uid).addSnapshotListener { (snapshot, error) in
        guard let documents = snapshot?.documents else {
                print("No Documents")
            
                return
            }
        
            self.user = documents.compactMap { queryDocumentSnapshot -> UserProfileModel? in
            
                 return try? queryDocumentSnapshot.data(as: UserProfileModel.self)
             }
        }
    }
}

View:

struct MainView: View {

    @ObservedObject private var viewModel = UserProfileViewModel()

    var body: some View { // -> Error: The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
        VStack{
            Text(viewModel.user.username) // -> I want to do this but XCode is giving an error.

            // This works but I don't want to do it this way.
            List(viewModel.user) { user in
                        VStack{
                            Text(user.username)
                            Text(user.firstName)
                            Text(user.lastName)
                            Text(user.email)
                            Text(user.uidFromFirebase)
                        }
                    }
        }
    }
}

In the videos and articles titled "SwiftUI fetch data from Firebase" that I watched and read, I have always narrated on List and ForEach. But I want to use the data wherever. I shared all my code with you. I want to learn how I can do this.

Upvotes: 1

Views: 1302

Answers (1)

jnpdx
jnpdx

Reputation: 52387

Looks to me like you really just want to have one user that you're pulling the data for, but you've set up your UserProfileViewModel with an array of users ([UserProfileModel]). There are a number of ways that you could take care of this. Here's one (check the code for inline comments about what is going on):

class UserProfileViewModel: ObservableObject {

    @Published var user : UserProfileModel? = nil // now an optional

    private var db = Firestore.firestore()

    func data(){
        db.collection("Users").whereField("uuidFromFirebase", isEqualTo: Auth.auth().currentUser!.uid).addSnapshotListener { (snapshot, error) in
        guard let documents = snapshot?.documents else {
                print("No Documents")
            
                return
            }
        
            self.user = documents.compactMap { queryDocumentSnapshot -> UserProfileModel? in
            
                 return try? queryDocumentSnapshot.data(as: UserProfileModel.self)
             }.first // Take the first document (since there probably should be only one anyway)
        }
    }
}
struct MainView: View {

    @ObservedObject private var viewModel = UserProfileViewModel()

    var body: some View {
        VStack {
          if let user = viewModel.user { //only display data if the user isn't nil
             Text(user.username)
             Text(user.firstName)
             Text(user.lastName)
             Text(user.email)
             Text(user.uidFromFirebase)
          }
        }
    }
}

I'd say a more traditional way of handling this might be to store your user profile document Users/uid/ -- that way you can just user document(uid) to find it rather than the whereField query.

Upvotes: 2

Related Questions