NSURLSession - 数据为零
Posted
技术标签:
【中文标题】NSURLSession - 数据为零【英文标题】:NSURLSession - data is nil 【发布时间】:2016-11-15 17:06:35 【问题描述】:我在尝试使用 NSURLSession 委托方法获取数据时遇到问题。我想出了这个错误:
"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'data parameter is nil'"
我不明白的是
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
CGFloat percentDone = (double)totalBytesWritten/(double)totalBytesExpectedToWrite;
NSLog(@"Pourcentage: %f", percentDone);
正在返回 1.000000,并调用以下委托方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
// Parse the JSON that came in
NSLog(@"DidComplete"); --> I can see this message
if (error)
NSLog(@"Error in finishLoading: %@", error.localizedDescription); --> but this message is not displayed. There is no error, only data returning nil resulting in a crash...
else
....
但是下面的方法没有调用
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *) response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
NSLog(@"DidReceiveResponse"); --> not displayed
completionHandler(NSURLSessionResponseAllow);
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
NSLog(@"DidReceiveData. Data: %@", data); --> not displayed
_downloadedData = [[NSMutableData alloc] init];
[_downloadedData appendData:data];
但是应该在 didCompleteWithError 之前调用它不是吗?我假设无法调用其他处理附加数据的方法,然后数据为零。
我确信我可以在服务器端获取数据,因为当我使用块方法(而不是委托方法)时,NSData 对应于我要查找的内容。
奇怪的是,这个错误是在我像这样更改配置会话之后出现的:
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession2 = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];
NSURL *url = [NSURL URLWithString:@"http://localhost:8888/download_list.php"];
NSURLSessionDownloadTask *dataTask = [defaultSession2 downloadTaskWithURL:url];
当它是这样的时候,我可以看到从服务器检索到的 NSData
NSURLSessionDataTask *dataTask = [defaultSession2 dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
if(error == nil)
NSString * text = [[NSString alloc] initWithData:data encoding: NSUTF8StringEncoding];
NSLog(@"Data = %@",text); -> text corresponds to the data I am looking for
];
但是不可能用块来调用委托。
知道“数据”是如何消失的吗?或者我应该在不使用块时改变一些东西?
感谢您的帮助!
【问题讨论】:
没关系,我很愚蠢,这是一个 NSURLSessionDownloadTask 而不是 NSURLSessionDataTask... 但是我有一个奇怪的消息:nw_host_stats_add_src recv 太小,收到 24,预期 28。有人知道这是什么意思? 不幸的是它并没有改变任何东西...... “奇怪的消息”是一个新问题。删除 Q 并创建一个新的。抓住真正的 Q 不是读者的任务。 我还没有真正理解新队列的目标是什么?我更改了 dataTask 并调用了委托方法,谢谢。 不是“队列”,而是“问题”。他的意思是,如果您对一些奇怪的日志消息有疑问,那是一个完全不同的问题,应该作为一个单独的问题发布,而不是在 cmets 中在这个问题下面提出。这里的问题似乎是“为什么我没有看到我的委托方法被调用?”,答案是“因为你使用了dataTaskWithURL
的完成处理程序再现。”
【参考方案1】:
如果您像这样调用dataTaskWithURL
,则不会调用didReceiveResponse
和didReceiveData
委托方法:
NSURLSessionDataTask *dataTask = [defaultSession2 dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
...
];
您正在提供一个完成处理程序,请求它为您捕获response
和data
。因此,为此,它不会调用委托方法。
如果你想调用你的委托方法,你应该:
NSURLSessionDataTask *dataTask = [defaultSession2 dataTaskWithURL:url];
不过,坦率地说,您目前在这些方法中没有做任何重要的事情,所以我想知道您为什么要使用委托方法而不是完成处理程序。完成处理程序模式更简单。
顺便说一句,如果您要使用这些方法,请确保 didReceiveData
仅附加。在didReceiveResponse
中实例化可变数据对象。接收整个响应可能需要多次didReceiveData
调用,并且您的原始代码示例将截断结果。您可能想要执行以下操作:
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *) response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
NSLog(@"DidReceiveResponse"); // will now be displayed
_downloadedData = [[NSMutableData alloc] init];
completionHandler(NSURLSessionResponseAllow);
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
NSLog(@"DidReceiveData. Data: %@", data); // will now be displayed
[_downloadedData appendData:data];
【讨论】:
以上是关于NSURLSession - 数据为零的主要内容,如果未能解决你的问题,请参考以下文章
无法在 iOS 中使用 NSURLSession 多部分表单数据上传文件