1

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

ただし、デリゲートをブロックで呼び出すことはできませんでした。

「データ」がどのように消えるか考えていますか? または、ブロックを使用していないときに何かを変更する必要がありますか?

助けてくれてありがとう!

4

1 に答える 1

1

次のように呼び出した場合didReceiveResponse、 およびデリゲート メソッドは呼び出されません。didReceiveDatadataTaskWithURL

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

responseandをキャプチャするように要求する完了ハンドラを提供していdataます。そのため、デリゲート メソッドは呼び出されません。

デリゲート メソッドを呼び出す場合は、次のようにする必要があります。

NSURLSessionDataTask *dataTask = [defaultSession2 dataTaskWithURL:url];

率直に言って、あなたは現在、これらのメソッドで重要なことを何も行っていないので、なぜ完了ハンドラーではなくデリゲート メソッドを使用したいのか疑問に思います。完了ハンドラー パターンはより単純です。


ちなみに、これらのメソッドを使用する場合は、didReceiveData追加のみを行うようにしてください。で変更可能なデータ オブジェクトをインスタンス化しますdidReceiveResponsedidReceiveData応答全体を受け取るには複数回の呼び出しが必要な場合があり、元のコード サンプルでは結果が切り詰められます。おそらく次のようなことをしたいでしょう:

- (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];
}
于 2016-11-16T17:46:34.100 に答える