简体   繁体   中英

why my observe value function to retrieve data from firebase database doesn't work for the first time?

I am trying to make a login system using google account to firebase authentication.

if the user login using google account for the first time , then they have to pick their city domicile first before go to HomeVC otherwise they can go straight to homeVC.

To tackle this issue, first I try to get the data from firebase database. if the user has been login before, then they will have user database in my firebase. so, the result from snapshot.value from observe it will be stored to userBasicInformation .

if the user login for the first time then userBasicInformation should be nil. but I don't know why the line of code that retrieve the data from my firebase database below seems never be executed in the first time

Database.database().reference().child("users/\(userKM.uid)").reference().observe

here is the simplified code of this login system. I give print number to track the code. the print result is below

import UIKit
import Firebase
import GoogleSignIn

//  variable that store user basic data (uid, fullname, email, domicile)
var userBasicInformation : [String:Any]?

// sign in using google account to Firebase Authenctication
Auth.auth().signIn(with: credential) { (user, error) in
            if let error = error {
                print("failed to create firebase user using google account")
                print("\(error.localizedDescription)")
                return
            }

            print("user successfully logged into firebase")

            print("1")

            guard let userKM = user else { return }

             print("2")
            // retrieve User Basic data from firebase database
            Database.database().reference().child("users/\(userKM.uid)").reference().observe(.value, with: { (snapshot) in

                 print("3")

                if let valueDictionary = snapshot.value as? [String:Any] {
                    let userValue = User(dictionary: valueDictionary)

                    let userInformation : [String:Any] = [

                        "uid" : userValue.uid,
                        "fullname" : userValue.fullname,
                        "email" : userValue.email,
                        "domicile" : userValue.domicile
                    ]

                    userBasicInformation = userInformation

                } else {
                     print("4")
                    // if there is no snapshott.value (no database for certain uid) then set to nil. it means user logged in using gmail forthe first time
                    userBasicInformation = nil
                }

            }) 

            // if user has signed up before then send to mainTabBar (it means he/she has picked a city), otherwise pickCity first
            // if the user sign Up for the first time, then userBasicInformation will be nil because there is no user default available

            if userBasicInformation == nil {

                 print("5")

                // save user data to Firebase Database
                let userX = User(uid: userKM.uid, fullname: userKM.displayName!, email: userKM.email!)
                userX.save(completion: { (error) in

                    if error != nil {
                       print(error!)
                    }

                })

                // assign Value to superGlobal Variable
                userBasicInformation = [
                    "uid" : userX.uid as Any,
                    "fullname" : userX.fullname as Any,
                    "email" : userX.email as Any,
                    "domicile" : userX.domicile as Any
                ]


              self.pickCity()

            } else {
                 print("6")
              self.goToMainTabBar()
            }         
        }        
    }

here is the result from my debugging area

  • user successfully signin into google
  • user successfully logged into firebase
  • 1
  • 2
  • 5
  • 3

i don't understand why '3' which is 'retrieving data from firebase database' using observe seems never be executed first

i expect 1 -> 2 -> 3 -> 5 , but i got 1 -> 2 -> 5 -> 3

thats why userBasicInformation always be nil if i restart the simulator

why my observe value doesn't work for the first time?

It is obvious.

Your execution of Database.database().reference().child("users/\\(userKM.uid)").reference().observe(.value, with: { (snapshot) in

is async operation and it will executed after response form your request

while you are

checking if userBasicInformation == nil { condition next to the that async block child("users/\\(userKM.uid)") , so it will executed first. (It will not wait for your firebase request child("users/\\(userKM.uid)") to finish)

To Fix this Put all the if userBasicInformation == nil { and else block in the your firebase request block.

Hope it is helpful to you

EDIT\\UPDATE

I don't understand why you are checking if userBasicInformation == nil { after putting this stuff inside users/\\(userKM.uid)" you don't need to check it is nil or not

if you wan't to user to login automatically if he did before then

in viewDidLoad put

  GIDSignIn.sharedInstance().signInSilently()

    Auth.auth().addStateDidChangeListener { (auth, user) in
        if user != nil {
         // HERE YOU CAN  PERFORM ANYTHING LIKE SAVING TO USERDEFAULT OR ANYTHING AFTER USER LOGGED IN
            UserDefaults.standard.setValue(user?.uid, forKeyPath: "uid")

            self.performSegue(withIdentifier: "CurrentlyLoggedIn", sender: nil)

        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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