'Swiftui - Fetch data after login

I'm starting to learn SwiftUI and i'm looking for better solution to fetch user data after successful login.

For example, i need to see if the user has the account blocked or not after login

For this i have create struct in Users.swift

struct Users: Identifiable, Codable{

    @DocumentID var id: String?
    var Societe : String
    var Nom : String
    var Prenom : String
    var HasBlocked : Bool
    var SiteID : [String]
    var Poste : String
    var Email : String
}

and firebase class in Firebase.swift

class Firebase: ObservableObject {
    
    @EnvironmentObject var viewRouter: ViewRouter
    @Published var user : Users? = nil

    private var db = Firestore.firestore()
    
    
        func fetchData() {
            db.collection("Users").document(Auth.auth().currentUser!.uid).addSnapshotListener{ (snapshot, error) in
                guard let documents = snapshot?.data() else {
                    print("No documents")
                    return
                }
                let name = documents["Nom"] as? String ?? ""
                let surname = documents["Prenom"] as? String ?? ""
                let email = documents["Email"] as? String ?? ""
                let societe = documents["Societe"] as? String ?? ""
                let poste = documents["Poste"] as? String ?? ""
                let siteId = documents["SiteID"] as? [String] ?? []
                let hasBlocked = documents["HasBlocked"] as? Bool ?? true
                
                if let user = self.user?.SiteID{
                    print(user)
                }else{
                    print("no document2")
                }
                
                self.user = Users(Societe: societe, Nom: name, Prenom: surname, HasBlocked: hasBlocked, SiteID: siteId, Poste: poste, Email: email)
                }
        }
}

and in the SignInView after press login button, i call func signInUser


@ObservedObject private var firebase = Firebase()

func signInUser(userEmail: String, userPassword: String) {
        
        signInProcessing = true
        
        Auth.auth().signIn(withEmail: email, password: password) { authResult, error in
        
            guard error == nil else {
                signInProcessing = false
                signInErrorMessage = error!.localizedDescription
                return
            }
            switch authResult {
            case .none:
                print("Could not sign in user.")
                signInProcessing = false
            case .some(_):
                print("User signed in")

                // get data and check ??

                signInProcessing = false
                withAnimation {
                    viewRouter.currentPage = .homePage
                }
            }
        }
    }

But i don't know how to fetch data after login for check if the account has blocked and then pass the data to Homeview without re-fetch data to optimize call database.

thank for your help



Solution 1:[1]

Let me address this at a high level as your code seems fine but its's just wrapping your brain around the asynchronous calls.

I am pretty sure you have everything you need - here's the flow using pseudo code

authenticate { auth closure
    read user document using auth.uid { snapshot closure
         if snapshot has user blocked {
            do not proceed to next view
         } else { //user is not blocked
            proceed to next view
         }
    }
}

Remember that Firebase data is only valid within the closure following the Firebase call and if you follow the above pseudo code, it does just that...

auth closure - has valid firebase auth information so you can get the uid

    snapshot closure  - has valid snapshot info so you can see if the user is blocked
    
        the If statement will then determine the next thing to do - either don't show
           the view if blocked or show it if not blocked

So borrowing from your code

func signInUser(userEmail: String, userPassword: String) {
        Auth.auth().signIn(withEmail: email, password: password) { authResult, error in
             db.collection("Users").document(Auth.auth().currentUser!.uid).getDocument {
                  either go to next view or not

Note that you should be using getDocument in this case to read the document once instead of adding a listener.

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