如何让应用程序等待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() }