Alamofire 中的错误处理
Error handling in Alamofire
我在 AngularJS 控制器中有 HTTP 代码:
$http.post('/api/users/authenticate', {email: $scope.email, password: $scope.password})
.success(function (data, status, headers, config) {
authService.login($scope.email);
$state.go('home');
})
.error(function (data, status, headers, config) {
$scope.errorMessages = data;
$scope.password = "";
});
在成功的情况下,服务器将响应一个 JSON 用户表示。在错误情况下,服务器将使用一个简单的字符串作为响应,例如 User not found
,可以通过 data
参数访问该字符串。
我不知道如何在 Alamofire 中做类似的事情。这是我现在拥有的:
@IBAction func LoginPressed(sender: AnyObject) {
let params: Dictionary<String,AnyObject> = ["email": emailField.text, "password": passwordField.text]
Alamofire.request(.POST, "http://localhost:3000/api/users/authenticate", parameters: params)
.responseJSON {(request, response, data, error) in
if error == nil {
dispatch_async(dispatch_get_main_queue(), {
let welcome = self.storyboard?.instantiateViewControllerWithIdentifier("login") as UINavigationController;
self.presentViewController(welcome, animated: true, completion: nil);
})
}
else{
dispatch_async(dispatch_get_main_queue(), {
// I want to set the error label to the simple message which I know the server will return
self.errorLabel.text = "something went wrong"
});
}
}
}
我也不知道我是否正确处理了非错误情况,也希望对此提出意见。
所以 Alamofire 将所有请求都视为成功。这实际上归结为 API 服务器 http headers 被返回。
你可以使用 Alamofire.Request.validate()
它将允许您验证 http headers 等。查看示例
https://github.com/Alamofire/Alamofire#validation
我假设错误消息将在 data
object.
要访问数据中的值,您可以执行类似
的操作
我不太确定你的 api 回复看起来如何,但在这个例子中
{
"message": "Could not authenticate"
}
let message: String? = data?.valueForKey("message") as String
您走在正确的轨道上,但是您将 运行 解决当前实施的一些关键问题。有一些低级别的 Alamofire 东西会让你绊倒,我想帮助你。这是您的代码示例的另一个版本,它会更有效。
@IBAction func loginPressed(sender: AnyObject) {
let params: [String: AnyObject] = ["email": emailField.text, "password": passwordField.text]
let request = Alamofire.request(.POST, "http://localhost:3000/api/users/authenticate", parameters: params)
request.validate()
request.response { [weak self] request, response, data, error in
if let strongSelf = self {
let data = data as? NSData
if data == nil {
println("Why didn't I get any data back?")
strongSelf.errorLabel.text = "something went wrong"
return
} else if let error = error {
let resultText = NSString(data: data!, encoding: NSUTF8StringEncoding)
println(resultText)
strongSelf.errorLabel.text = "something went wrong"
return
}
var serializationError: NSError?
if let json: AnyObject = NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments, error: &serializationError) {
println("JSON: \(json)")
let welcome = self.storyboard?.instantiateViewControllerWithIdentifier("login") as UINavigationController
self.presentViewController(welcome, animated: true, completion: nil)
} else {
println("Failed to serialize json: \(serializationError)")
}
}
}
}
验证
首先,请求中的 validate
函数将验证以下内容:
HTTPStatusCode
- 必须为 200...299
Content-Type
- 响应中的这个 header 必须匹配原始请求中的 Accept
header
您可以在 README.
中找到有关 Alamofire 验证的更多信息
弱化/强化
确保你的闭包弱化自我并强化自我,以确保你最终不会创建一个保留周期。
调度到主Queue
您的调度调用回主 queue 是没有必要的。 Alamofire 保证 response
和 responseJSON
序列化程序中的完成处理程序已经在主 queue 上调用。如果你愿意,你实际上可以提供你自己的调度 queue 到 运行 序列化器,但是你的解决方案或我的解决方案目前都没有这样做,使得对主 queue 的调度调用完全没有必要。
响应序列化器
在您的特定情况下,您实际上并不想使用 responseJSON
序列化程序。如果这样做,如果您没有通过验证,您将不会最终获得任何数据。原因是来自 JSON 序列化的响应将作为 AnyObject
返回。如果序列化失败,AnyObject
将为 nil,您将无法读取数据。
相反,使用 response
序列化程序并尝试使用 NSJSONSerialization
手动解析数据。如果失败,那么您可以依靠好的 ole NSString(data:encoding:)
方法来打印数据。
希望这有助于阐明一些相当复杂的被绊倒的方法。
我在 AngularJS 控制器中有 HTTP 代码:
$http.post('/api/users/authenticate', {email: $scope.email, password: $scope.password})
.success(function (data, status, headers, config) {
authService.login($scope.email);
$state.go('home');
})
.error(function (data, status, headers, config) {
$scope.errorMessages = data;
$scope.password = "";
});
在成功的情况下,服务器将响应一个 JSON 用户表示。在错误情况下,服务器将使用一个简单的字符串作为响应,例如 User not found
,可以通过 data
参数访问该字符串。
我不知道如何在 Alamofire 中做类似的事情。这是我现在拥有的:
@IBAction func LoginPressed(sender: AnyObject) {
let params: Dictionary<String,AnyObject> = ["email": emailField.text, "password": passwordField.text]
Alamofire.request(.POST, "http://localhost:3000/api/users/authenticate", parameters: params)
.responseJSON {(request, response, data, error) in
if error == nil {
dispatch_async(dispatch_get_main_queue(), {
let welcome = self.storyboard?.instantiateViewControllerWithIdentifier("login") as UINavigationController;
self.presentViewController(welcome, animated: true, completion: nil);
})
}
else{
dispatch_async(dispatch_get_main_queue(), {
// I want to set the error label to the simple message which I know the server will return
self.errorLabel.text = "something went wrong"
});
}
}
}
我也不知道我是否正确处理了非错误情况,也希望对此提出意见。
所以 Alamofire 将所有请求都视为成功。这实际上归结为 API 服务器 http headers 被返回。
你可以使用 Alamofire.Request.validate()
它将允许您验证 http headers 等。查看示例
https://github.com/Alamofire/Alamofire#validation
我假设错误消息将在 data
object.
要访问数据中的值,您可以执行类似
的操作我不太确定你的 api 回复看起来如何,但在这个例子中
{
"message": "Could not authenticate"
}
let message: String? = data?.valueForKey("message") as String
您走在正确的轨道上,但是您将 运行 解决当前实施的一些关键问题。有一些低级别的 Alamofire 东西会让你绊倒,我想帮助你。这是您的代码示例的另一个版本,它会更有效。
@IBAction func loginPressed(sender: AnyObject) {
let params: [String: AnyObject] = ["email": emailField.text, "password": passwordField.text]
let request = Alamofire.request(.POST, "http://localhost:3000/api/users/authenticate", parameters: params)
request.validate()
request.response { [weak self] request, response, data, error in
if let strongSelf = self {
let data = data as? NSData
if data == nil {
println("Why didn't I get any data back?")
strongSelf.errorLabel.text = "something went wrong"
return
} else if let error = error {
let resultText = NSString(data: data!, encoding: NSUTF8StringEncoding)
println(resultText)
strongSelf.errorLabel.text = "something went wrong"
return
}
var serializationError: NSError?
if let json: AnyObject = NSJSONSerialization.JSONObjectWithData(data!, options: .AllowFragments, error: &serializationError) {
println("JSON: \(json)")
let welcome = self.storyboard?.instantiateViewControllerWithIdentifier("login") as UINavigationController
self.presentViewController(welcome, animated: true, completion: nil)
} else {
println("Failed to serialize json: \(serializationError)")
}
}
}
}
验证
首先,请求中的 validate
函数将验证以下内容:
HTTPStatusCode
- 必须为 200...299Content-Type
- 响应中的这个 header 必须匹配原始请求中的Accept
header
您可以在 README.
中找到有关 Alamofire 验证的更多信息弱化/强化
确保你的闭包弱化自我并强化自我,以确保你最终不会创建一个保留周期。
调度到主Queue
您的调度调用回主 queue 是没有必要的。 Alamofire 保证 response
和 responseJSON
序列化程序中的完成处理程序已经在主 queue 上调用。如果你愿意,你实际上可以提供你自己的调度 queue 到 运行 序列化器,但是你的解决方案或我的解决方案目前都没有这样做,使得对主 queue 的调度调用完全没有必要。
响应序列化器
在您的特定情况下,您实际上并不想使用 responseJSON
序列化程序。如果这样做,如果您没有通过验证,您将不会最终获得任何数据。原因是来自 JSON 序列化的响应将作为 AnyObject
返回。如果序列化失败,AnyObject
将为 nil,您将无法读取数据。
相反,使用 response
序列化程序并尝试使用 NSJSONSerialization
手动解析数据。如果失败,那么您可以依靠好的 ole NSString(data:encoding:)
方法来打印数据。
希望这有助于阐明一些相当复杂的被绊倒的方法。