简介
-
网络请求时,出现标题那样的error,原因很多,这里记录一次自己遇到的原因。
-
代码如下
#pragma mark - 网络请求测试
- (void)test{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:delegateObject delegateQueue:[NSOperationQueue mainQueue]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:@"api.com"];
request.HTTPBody = para//请求数据
NSURLSessionTask *task = [session dataTaskWithRequest:request];
[task resume];
}
#pragma mark - NSURLSessionDelegate method
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
DeLog(@"1。 %s",__FUNCTION__);
completionHandler(NSURLSessionResponseAllow);
}
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
NSError *error;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:self.recevieData options:NSJSONReadingMutableLeaves error:&error];
if (error)
{
NSLog(@"initSDK error === %@",error.localizedDescription);
}
}
-(void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error{
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error
{
[session finishTasksAndInvalidate];
}
打印结果:
initSDK error === The data couldn’t be read because it isn’t in the correct format
分析
-
经过分析发现,
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
的data有时候取到不是完整的全部数据. -
[NSByteCountFormatter stringFromByteCount:data countStyle:NSByteCountFormatterCountStyleFile]
打印,完整的data
=2KB
,报错的data
=1KB
。 -
取到的
data
=2KB
/data
=1KB
是随机出现。 -
data
其实是一个json
,分别把data
转成NSDictionary
和NSString
,NSDictionary
=nil
,而NSString
有值,但是只是完整的json
的一部分 -
在我的例子当中,当
data
=1KB
的时候,-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
实际上会调用两次,我把前后两次的data
拼接起来,恰巧就是一个完整的json
。而当data
=2KB
,只调用一次 -
答案很明显了。
解决
- 既然
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
得到data
不一定是最终的data
,而且可能会调用多次,那么为了得到一个纯净的,完整的json
,就得找到一个NSURLSessionDelegate
众多方法中,必须会调用,而且是整个请求过程完成后,最后调用的一方法,这个方法还只能被调用一次。 -
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error
完美的解决了这个问题。因为通常我们释放session
,也会放在这个方法中。 - 上面例子解决代码
#pragma mark - NSURLSessionDelegate method
#pragma mark - 设置一个全局变量,接收data
NSMutableData *_data;
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
if(_data)
{
_data = [[NSMutableData alloc] init];
}
[_data appendData:data];
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error
{
#pragma这里取的_data,就可以得到完整的json
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:_data options:NSJSONReadingMutableLeaves error:&error];
[session finishTasksAndInvalidate];
}
- 经过循环请求5000次,没有出现
data
=1KB
的情况 - 不使用代理的方式,使用block的方式,block的data是不会出现这种情况。
网友评论