如何让应用程序等待Firebase请求完成
我希望我的方法等到Firebase请求完成
uploadSingUpInfo
在Firebase请求结束之前返回,这对我来说是一个问题 – 有些方法返回nil。
static func uploadSingUpInfo(fullName:String,email:String,password:String)->String{ rootRef = FIRDatabase.database().reference() var returnVlue="not valid" FIRAuth.auth()?.createUserWithEmail(email, password: password) { (user, error) in if (error != nil){ returnVlue=(error?.userInfo["error_name"]) as! String } else{ let newUser = [ "username": fullName ] rootRef.childByAppendingPath("User") .childByAppendingPath((user?.uid)!).setValue(newUser) NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isLogin") NSUserDefaults.standardUserDefaults().setObject(email, forKey: "email") NSUserDefaults.standardUserDefaults().setObject(user?.uid, forKey: "user_ID") print(NSUserDefaults.standardUserDefaults().objectForKey("user_ID")) returnVlue="valid" } } return returnVlue }
在您的代码中,该方法在returnVlue
请求完成之前返回,因此不会设置returnVlue
的值。
正常函数不等待asynchronous函数完成运行; – 因为这是asynchronous函数的一个点。 不是吗?
所以如果你想让uploadSingUpInfo
等到createUserWithEmail
完成,那么你必须通过使用completionHandlers来使createUserWithEmail
成为一个asynchronous函数:
func uploadSingUpInfo(fullName: String, email: String, password: String, completion: (result: String) -> Void) { FIRAuth.auth()?.createUserWithEmail(email, password: password) { (user, error) in if (error != nil){ returnVlue=(error?.userInfo["error_name"]) as! String } else{ let newUser = [ "username": fullName ] rootRef.childByAppendingPath("User") .childByAppendingPath((user?.uid)!).setValue(newUser) NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isLogin") NSUserDefaults.standardUserDefaults().setObject(email, forKey: "email") NSUserDefaults.standardUserDefaults().setObject(user?.uid, forKey: "user_ID") print(NSUserDefaults.standardUserDefaults().objectForKey("user_ID")) returnVlue="valid" } completion(returnVlue); } }
这就是你如何调用这个方法:
uploadSingUpInfo(<arguments>) { (result: String) in //this is what you pass to completion handler. print("got back: \(result)") }
看到这篇文章是一个更好的主意。
不要使用Firebase作为返回值的函数 – 它违背了它的asynchronous性质。
规划允许Firebase执行任务的代码结构,然后在closures(块)内转到下一步。
例如:在您的代码中,将函数更改为不返回任何内容,并在createUserBlock中作为最后一行而不是返回,请调用下一个函数来更新UI。
static func uploadSingUpInfo(fullName:String,email:String,password:String) { rootRef = FIRDatabase.database().reference() FIRAuth.auth()?.createUserWithEmail(email, password: password) { (user, error) in if (error != nil){ showUserAnError(error) } else { let newUser = [ "username": fullName ] rootRef.childByAppendingPath("User") .childByAppendingPath((user?.uid)!).setValue(newUser) NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isLogin") NSUserDefaults.standardUserDefaults().setObject(email, forKey: "email") NSUserDefaults.standardUserDefaults().setObject(user?.uid, forKey: "user_ID") print(NSUserDefaults.standardUserDefaults().objectForKey("user_ID")) continueLoginProcess() //reload the ui or whatever step is next } } }
而不是从该函数返回一个值。 您可以在方法的“最后”调用firebase方法内的另一个函数。 这将确保无论您需要执行的任何function,都会在Firebase处理完您的请求后执行
FIRAuth.auth()?.createUserWithEmail(email, password: password) { (user, error) in if (error != nil){ returnVlue=(error?.userInfo["error_name"]) as! String } else{ let newUser = [ "username": fullName ] rootRef.childByAppendingPath("User") .childByAppendingPath((user?.uid)!).setValue(newUser) NSUserDefaults.standardUserDefaults().setBool(true, forKey: "isLogin") NSUserDefaults.standardUserDefaults().setObject(email, forKey: "email") NSUserDefaults.standardUserDefaults().setObject(user?.uid, forKey: "user_ID") print(NSUserDefaults.standardUserDefaults().objectForKey("user_ID")) returnVlue="valid" } callAnotherFunctionWhenFinished() }