[AFN]使用AFNetworking遇到的问题总结

2020-04-03  本文已影响0人  Young_LI

1. 使用 BaseURL 发送请求, 丢失地址路径

在维护网络请求的 API 时, 一般都是使用 “baseURL + 相对地址” 的方式, 即:

#define baseURL @"https://www.baidu.com/"

#define login @"/login"

这样在使用的时候, 没什么问题, 但是, 如果你是下面这样定义的, 可能就有问题了:

#define baseURL @"https://www.baidu.com/app/"

#define login @"/login"

会一直打印 404 的错误信息, 而地址变成了https://www.baidu.com/login

最后, 查看源码, 发现问题出在, AFN 内使用的这么一个方法使用上

+(nullable instancetype)URLWithString:(NSString*)URLString relativeToURL:(nullable NSURL*)baseURL;

这是系统的一个方法, 具体原因可以查看这篇文章:ios-NSURL URLWithString:relativeToURL的坑

定义 API 的时候, 要么 baseURL 只用 host 地址, 要么就按下面的格式来定义:

baseURL 使用 / 结尾

相对路径开头不能加 /

2. The data couldn’t be read because it isn’t in the correct format

这个问题是使用AFN发送POST请求时遇到的,奇怪的是使用GET请求能够正常拿到数据,而使用POST就不行;

控制台输出如下信息:

http://192.168.69.121:8080/artboss-webapp/ios/checkcodeparams:{"user_phonenumber"=185****0925;}errorInfos:Thedata couldn’t be read because it isn’tinthe correct format.

大意就是数据没有正确的被格式化,无法读取!后台也接收不到我传递的参数;

使用Charles抓包会发现是这样的信息:

HTTP Status400-Request String parameter'user_phonenumber'isnot present

400 Bad Request!

我一看是非法的网络请求,以为是我的问题,就一直在我这边找原因,

最后才发现,这是因为我发送请求时发送的字符串,和后台需要的字符串格式不一致,发送请求时,后台需要的是text文本格式,而我发送的是json格式,导致后台无法识别,接收不到数据!

后来发现我所用的封装类里的请求头,有如下设置:

[manager.requestSerializer setValue:@"application/json"forHTTPHeaderField:@"Accept"];[manager.requestSerializer setValue:@"application/json"forHTTPHeaderField:@"Content-Type"];

即,默认是使用json传输数据的!

把第二个注释掉,即使用默认的Content-Type,

并在发送请求时设置发送的字段为文本格式,即:

manager.requestSerializer = [AFHTTPRequestSerializer serializer];

本以为会解决问题,但事实还是请求不到数据!!

最后不得已使用原生的AFNetworking进行测试,post正常拿到了数据,后来对比两者的区别,除了上面的改动以外,请求返回的数据也要改为文本,即:

manager.responseSerializer = [AFHTTPResponseSerializer serializer];

这样才正常拿到了数据!!

总之,此次网络请求的异常,是由于请求和响应的文本格式没有统一,导致参数无法正常传递,数据无法正常读取!

3. Invalid parameter not satisfying: body

在使用AFNetworking进行传图操作的时候,出现了这个crash信息:

模拟器运行后控制台输出:

Terminating app due to uncaught exception'NSInternalInconsistencyException',reason:'Invalid parameter not satisfying: body'***Firstthrowcall stack:(0CoreFoundation0x0000000107ad4e65__exceptionPreprocess+1651libobjc.A.dylib0x0000000106c1edebobjc_exception_throw+482CoreFoundation0x0000000107ad4cca+[NSException raise:format:arguments:]+1063Foundation0x000000010431d4de-[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]+198)libc++abi.dylib:terminatingwithuncaught exceptionoftypeNSException

真机的话会输出如下信息:

***Terminating app due to uncaught exception'NSInternalInconsistencyException',reason:'Invalid parameter not satisfying: body'***Firstthrowcall stack:(0x225e62eb0x21db2dff0x225e61c10x22dbcd3b0x1b8d3f0x1b89810x1909f10x1b4a6b0x1a1be90x1906c10x1765350x1771710x1933710x18f5cb0x19fbb90x8dfcbf0x8dfcab0x8e47710x225a8fc50x225a74bf0x224f9bb90x224f99ad0x23773af90x267e5fb50x118b110x221ac873)libc++abi.dylib:terminating with uncaught exception of type NSException(lldb)

而且crash的地方也不一样:

模拟器crash到自动释放池

模拟器crash

真机的话carsh到AFN的底层:

真机crash

其实,最主要的信息就是:Invalid parameter not satisfying: body(无效的参数:body)

问题就出在body这个参数上,模拟器上看不出什么头绪,请求参数中也没有body这个参数;但是在真机上的crash信息可以看出一些头绪:他是crash到了这个方法里

-(void)appendPartWithHeaders:(NSDictionary*)headers                          body:(NSData*)body{NSParameterAssert(body);AFHTTPBodyPart*bodyPart=[[AFHTTPBodyPart alloc]init];bodyPart.stringEncoding=self.stringEncoding;bodyPart.headers=headers;bodyPart.boundary=self.boundary;bodyPart.bodyContentLength=[body length];bodyPart.body=body;[self.bodyStream appendHTTPBodyPart:bodyPart];}

可以看到body的类型是NSData,而设置的请求参数中,只有要发送的照片数据是NSData类型,是不是照片的问题呢?进到AFN的底层可以发现,AFN上传图片主要是用到了这个方法:

-(void)appendPartWithFileData:(NSData*)data                            name:(NSString*)name                        fileName:(NSString*)fileName                        mimeType:(NSString*)mimeType{NSParameterAssert(name);NSParameterAssert(fileName);NSParameterAssert(mimeType);NSMutableDictionary*mutableHeaders=[NSMutableDictionary dictionary];[mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"",name,fileName]forKey:@"Content-Disposition"];[mutableHeaders setValue:mimeType forKey:@"Content-Type"];[selfappendPartWithHeaders:mutableHeaders body:data];}

在这个方法里调用了

[self appendPartWithHeaders:mutableHeaders body:data];

正是,程序crash的地方;

其实,打断点调试后也能发现传入的照片数据为nil,问题的根源找到了,问题也就解决了!!!

4. terminating with uncaught exception of type NSException

虽然上面那个问题中也有这句输出,但是这次除了这句没有其他信息,上面的还有其他比较多的信息以供排查问题,这次是这样的:

什么鬼都看不出来...

检查了各种参数,都没有问题,最后不得已,断点一步步执行,最后发现是请求时的数据格式问题;

AFN的默认请求的数据格式为JSON,这也是大多数后台使用的数据格式,同样返回格式也是JSON;

但是,但是,但是...重要的事情说三遍,总有不支持JSON的后台接口.......

最后,我设置了一下请求头的请求数据格式,即:

manager.requestSerializer = [AFHTTPRequestSerializer serializer];

最后就可以正常发送请求了;

作者:流火绯瞳

链接:https://www.jianshu.com/p/270bfa6fb7a3

来源:简书

上一篇下一篇

猜你喜欢

热点阅读