我正在尝试使用Google帐户创建登录系统以进行firebase身份验证。
如果用户首次使用谷歌帐户登录,那么他们必须首先选择他们的城市住所才能转到HomeVC,否则他们可以直接进入homeVC。
要解决此问题,首先我尝试从firebase数据库中获取数据。如果用户之前已经登录过,那么他们将在我的firebase中拥有用户数据库。因此,来自snapshot.value
的{{1}}的结果将存储到observe
。
如果用户第一次登录,那么userBasicInformation
应为零。但我不知道为什么从我的firebase数据库中检索数据的代码行似乎永远不会在第一次执行
userBasicInformation
这是此登录系统的简化代码。我给出打印号码来跟踪代码。打印结果低于
Database.database().reference().child("users/\(userKM.uid)").reference().observe
这是调试区域的结果
- 用户成功登录谷歌
- 用户成功登录firebase
- 1
- 2
- 5
- 3
我不明白为什么'3'使用observe从'firebase数据库中检索数据'似乎永远不会先执行
我希望1 - > 2 - > 3 - > 5 , 但我得到了1 - > 2 - > 5 - > 3
这就是为什么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()
}
}
}
如果重新启动模拟器
为什么我的观察值第一次不起作用?
答案 0 :(得分:1)
很明显。
执行Database.database().reference().child("users/\(userKM.uid)").reference().observe(.value, with: { (snapshot) in
是异步操作,它将在您的请求响应后执行
当你
时检查该异步块if userBasicInformation == nil {
旁边的child("users/\(userKM.uid)")
条件,因此它将首先执行。 (它不会等待你的firebase请求child("users/\(userKM.uid)")
完成)
解决此问题将所有if userBasicInformation == nil {
和else
块放入您的firebase请求块中。
希望它对你有所帮助
修改\ UPDATE 强>
我不明白为什么在把这些东西放进if userBasicInformation == nil {
之后你正在检查users/\(userKM.uid)"
你不需要检查它是否为零
如果你不想让用户自动登录,那么
在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)
}
}