在函数外使用来自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
nil
, jsonString
一些错误,但是您再也不知道有关错误的任何信息,那么您有两个select:
- 改变你的闭包始终返回
jsonString
和error
- 将错误封装成可抛出的闭包。
第一种情况很简单,只要改变你的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闭包
我希望这可以帮助你。