美文网首页
iOS NSURLSession的坑(The data coul

iOS NSURLSession的坑(The data coul

作者: 突刺刺 | 来源:发表于2018-09-03 19:39 被阅读12次

简介

  • 网络请求时,出现标题那样的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转成NSDictionaryNSString,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是不会出现这种情况。

相关文章

网友评论

      本文标题:iOS NSURLSession的坑(The data coul

      本文链接:https://www.haomeiwen.com/subject/lcuiwftx.html