一般的服务端框架返回的数据格式是确定的,在客户端和服务端交互的时候,如果交互成功那么服务端返回的状态码是200,具体的数据信息会放在字典的内层。
{
"status":200,
"info":{
"code":0,
"data": {
"total": 345
},
"message": "成功",
"token": null
}
}
如果交互成功,但是权限问题的返回信息状态码也是200,200表示交互成功,错误码会在内层包裹,而app的AFN接收之后会直接走请求成功的回调,从请求成功的回调里面拿到数据
[manager POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
completionHandle(responseObject,nil);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
{
"status":200,
"info":{
"code":401,
"data": {
"total": 345
},
"message": "认证失效",
"token": null
}
}
那么问题来了,最近公司开发的项目中,服务端的框架对请求的处理有所不同。如果是成功回调,那么返回的数据就和之前的一样,外层有200的状态码,内层有数据。
{
"status":200,
"info":{
"code":0,
"data": {
"total": 345
},
"message": "成功",
"token": null
}
}
新架构的失败回调的数据和原有的数据有所不同:
内层的401或者404居然跑到最外层了
{
"status":401,
"info":{
"code":401,
"data": {
"total": 345
},
"message": "认证失效",
"token": null
}
}
这种情况下,AFN直接走的失败回调了,在数据处理方便,因为拿不到具体的字典内容,所以后续的数据处理就成了问题。
于是只能从这个失败回调的方法里面找信息。
下面是控制台打印的数据:
(lldb) po error
Error Domain=com.alamofire.error.serialization.response Code=-1011
"Request failed: unauthorized (401)"
UserInfo={NSLocalizedDescription=Request failed: unauthorized (401),
NSErrorFailingURLKey=https://pile-test.haipaiyc.com/order/gun, com.alamofire.serialization.response.error.data=
<7b0a2020 22737461 74757322 203a2034 30312c0a 2020226d 65737361 67652220 3a2022e8 aea4e8af 81e5a4b1 e6958822 2c0a2020 22657272 6f727322 203a205b 20224675 6c6c2061 75746865 6e746963 6174696f 6e206973 20726571 75697265 6420746f 20616363 65737320 74686973 20726573 6f757263 6522205d 2c0a2020 22657863 65707469 6f6e4e61 6d652220 3a202249 6e737566 66696369 656e7441 75746865 6e746963 6174696f 6e457863 65707469 6f6e220a 7d>, com.alamofire.serialization.response.error.response=
{ URL: https://pile-test.haipaiyc.com/order/gun } { Status Code: 401, Headers {
"Connection" : [
"keep-alive"
],
"Content-Type" : [
"application\/json;charset=UTF-8"
],
"Server" : [
"nginx\/1.12.2"
],
"Pragma" : [
"no-cache"
],
"Expires" : [
"0"
],
"X-Content-Type-Options" : [
"nosniff"
],
"Date" : [
"Fri, 01 Nov 2019 03:42:00 GMT"
],
"X-Frame-Options" : [
"DENY"
],
"X-XSS-Protection" : [
"1; mode=block"
],
"Cache-Control" : [
"no-cache, no-store, max-age=0, must-revalidate"
],
"Transfer-Encoding" : [
"Identity"
]
} }}
想要拿到Error里面的具体信息,只能在通过NSError类来操作数据。
下面是NSError类
@interface NSError : NSObject {
@private
void *_reserved;
NSInteger _code;
NSString *_domain;
NSDictionary *_userInfo;
}
这样的话就看到希望了,使用控制台打印下error的各种属性,
(lldb) po error.userInfo
0x00000002818ba4c0
这样来取值看来行不通,可是为什么直接从控制台来po error的时候就会有这个401的状态码展示出来呢,在这里纠结了快1个小时也没解决,最后在上看到大神文章解决了这个问题。
直接上代码
NSData * data= error.userInfo[@"com.alamofire.serialization.response.error.data"];
NSDictionary * errorDic = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingAllowFragments error:nil];
具体就可以将这两行取值和转数据类型的代码放在AFN的失败回调里面:
[manager POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
completionHandle(responseObject,nil);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSData * data=
error.userInfo[@"com.alamofire.serialization.response.error.data"];
NSDictionary * errorDic =
[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
completionHandle(errorDic,error);
}];
这样就取到了想要的内层数据信息:
{
"status": 401,
"message": "认证失效",
"errors": [
"认证失效"
],
"exceptionName": "CredentialsExpiredException"
}
总结:
1.因为error.code直接可以打印出来,而error.userInfo打印出来就是二进制,所以没想到要将error.userInfo类型尝试转换。
2.在控制台打印到的数据中已经有关于com.alamofire.serialization.response.error.data这样的信息,只是没有往深处去追究,以为是字符串信息,所以就没办法进行取值操作。
文章参考来源:https://www.jianshu.com/p/644b17e4c7cd