在函数外使用来自Alamofire请求的值

我似乎无法弄清楚这一个:我试图从我的服务器(在JSON中)使用Alamofire请求的错误,但我不能得到该函数以外的值。

这是我的function的实现:

func alamoRequest(username : String, email: String, password: String, facebook: String, completionHandler : (String?) -> Void) { var jsonValue : JSON? let URL = "http://someurl.com/login.php" let requestParameters = ["username" : username, "email" : email, "password" : password, "facebook" : facebook, "date": NSNull()]; var jsonString : String = String() Alamofire.request(.GET, URL, parameters: requestParameters).validate().responseJSON { response in switch response.result { case .Success: if let value = response.result.value { jsonValue = JSON(value) jsonString = jsonValue!["error"].stringValue print("Value in implementation is: \(jsonString)") } case .Failure(let error): print(error) } } completionHandler(jsonString) } 

这就是我所说的:

 logic.alamoRequest(usernameField.text!, email: emailField.text!, password: passwordField.text!, facebook: "false") { json in jsonString = json! } alamoRequest = jsonString print("Value in call is: \(alamoRequest)) 

但是输出总是这样的:

Value from call is: Value in implementation is: Email already exists

如何从函数中“返回”某些东西,或者等待它执行而不会阻塞UI?

你的操作是asynchronous的 ,等待完成的方式只是使用闭包,你试图返回闭包外的值,所以值不被检索! 这是你的空值的原因,你可以像下面的例子那样“抛出” completionHandler在你的闭包中:

 func alamoRequest(username : String, email: String, password: String, facebook: String, completionHandler : (String?) -> Void) { var jsonValue : JSON? let URL = "http://someurl.com/login.php" let requestParameters = ["username" : username, "email" : email, "password" : password, "facebook" : facebook, "date": NSNull()]; var jsonString : String = String() Alamofire.request(.GET, URL, parameters: requestParameters).validate().responseJSON { response in switch response.result { case .Success: if let value = response.result.value { jsonValue = JSON(value) jsonString = jsonValue!["error"].stringValue print("Value in implementation is: \(jsonString)") completionHandler(jsonString) } case .Failure(let error): print(error) } } } 

不过,在上面的方式中,你不知道是否在请求中存在一些错误,因为你的completionHandler只在.Success情况下被调用,如果你想要,你可以随时调用它,在enum的最后一个case

 Alamofire.request(.GET, URL, parameters: requestParameters).validate().responseJSON { response in switch response.result { case .Success: if let value = response.result.value { jsonValue = JSON(value) jsonString = jsonValue!["error"].stringValue print("Value in implementation is: \(jsonString)") } case .Failure(let error): jsonString = nil } completionHandler(jsonString) } } 

如果jsonString niljsonString一些错误,但是您再也不知道有关错误的任何信息,那么您有两个select:

  1. 改变你的闭包始终返回jsonStringerror
  2. 将错误封装成可抛出的闭包。

第一种情况很简单,只要改变你的closures,并总是返回错误,如果nil那么没有错误发生。

我认为另一个select是更好的,就像下面的例子:

 func alamoRequest(username : String, email: String, password: String, facebook: String, completion: (inner: () throws -> String) -> ()) { var jsonValue : JSON? let URL = "http://someurl.com/login.php" let requestParameters = ["username" : username, "email" : email, "password" : password, "facebook" : facebook, "date": NSNull()]; var jsonString : String = String() Alamofire.request(.GET, URL, parameters: requestParameters).validate().responseJSON { response in switch response.result { case .Success: if let value = response.result.value { jsonValue = JSON(value) jsonString = jsonValue!["error"].stringValue print("Value in implementation is: \(jsonString)") completionHandler(inner: { return jsonString }) } case .Failure(let error): completionHandler(inner: { return error }) } } } 

然后你可以像下面这样调用它:

 self.alamoRequest(usernameField.text!, email: emailField.text!, password: passwordField.text!, facebook: "false") { (inner: () throws -> String) -> Void in do { let result = try inner() } catch let error { print(error) } } 

关键是alamoRequest函数需要一个额外的闭包,称为'inner'types() throws -> String 。 这个闭包将提供计算的结果,否则会抛出。 封闭本身是通过以下两种方法之一在计算过程中构build的:

  • 在发生错误的情况下: inner: {throw error}
  • 如果成功: inner: {return result}

我强烈build议你一个关于在asynchronous调用中使用try / catch的优秀文章在Swift中使用try / catch和asynchronous闭包

我希望这可以帮助你。