iOS NSURLSession的坑(The data couldn’t be read because it isn’t in the correct format)

簡介

  • 網(wǎng)絡(luò)請(qǐng)求時(shí),出現(xiàn)標(biāo)題那樣的error,原因很多,這里記錄一次自己遇到的原因。

  • 代碼如下

#pragma mark - 網(wǎng)絡(luò)請(qǐng)求測試
- (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//請(qǐng)求數(shù)據(jù)
    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];
}

打印結(jié)果:
initSDK error === The data couldn’t be read because it isn’t in the correct format

分析

  • 經(jīng)過分析發(fā)現(xiàn),-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data的data有時(shí)候取到不是完整的全部數(shù)據(jù).

  • [NSByteCountFormatter stringFromByteCount:data countStyle:NSByteCountFormatterCountStyleFile]打印,完整的data=2KB,報(bào)錯(cuò)的data=1KB。

  • 取到的data=2KB/data=1KB是隨機(jī)出現(xiàn)。

  • data其實(shí)是一個(gè)json,分別把data轉(zhuǎn)成NSDictionaryNSString,NSDictionary=nil,而NSString有值,但是只是完整的json的一部分

  • 在我的例子當(dāng)中,當(dāng)data=1KB的時(shí)候,-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data實(shí)際上會(huì)調(diào)用兩次,我把前后兩次的data拼接起來,恰巧就是一個(gè)完整的json。而當(dāng)data=2KB,只調(diào)用一次

  • 答案很明顯了。

解決

  • 既然-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data得到data不一定是最終的data,而且可能會(huì)調(diào)用多次,那么為了得到一個(gè)純凈的,完整的json,就得找到一個(gè)NSURLSessionDelegate眾多方法中,必須會(huì)調(diào)用,而且是整個(gè)請(qǐng)求過程完成后,最后調(diào)用的一方法,這個(gè)方法還只能被調(diào)用一次。
  • - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error完美的解決了這個(gè)問題。因?yàn)橥ǔN覀冡尫?code>session,也會(huì)放在這個(gè)方法中。
  • 上面例子解決代碼
#pragma mark - NSURLSessionDelegate method
#pragma mark - 設(shè)置一個(gè)全局變量,接收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];
}
  • 經(jīng)過循環(huán)請(qǐng)求5000次,沒有出現(xiàn)data=1KB的情況
  • 不使用代理的方式,使用block的方式,block的data是不會(huì)出現(xiàn)這種情況。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容