NSURLSession - 数据为零

时间:2016-11-15 17:06:35

标签: objective-c delegates nsdata nsurlsession nsurlsessionconfiguration

尝试使用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
    }
}];

然而,用一个块来调用代表是不可能的。

知道"数据"消失了?或者我不应该在不使用该块时改变一些东西?

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

如果您像这样致电didReceiveResponse,则不会调用didReceiveDatadataTaskWithURL委托方法:

NSURLSessionDataTask *dataTask = [defaultSession2 dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    ...
}];

您正在提供完成处理程序,要求它为您捕获responsedata。因此,要做到这一点,它不会调用委托方法。

如果你想要调用你的委托方法,你应该只是:

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];
}