NSURLSessionDownloadTask - read downloaded data before didFinishDownloading
Asked Answered
F

1

8

I am trying to replace NSURLConnection with NSURLSession, but I found that with NSURLSession I couldn't read the intermediate data chunks like I did in NSURLConnection with the delegate method.

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

I used to start using the data before completion. I am kind of streaming. How I can access the downloaded data before NSURLSession complete?

I notice there is a (NSURL *)location which is temporary saved data location from NSURLSession before completion, but I can I get this URL before completion?

Thanks


Tried this as suggested from Rob:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionTask *task = [session dataTaskWithRequest:request];
[task resume];

However, only didRecieveResponse was called

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler

but didReceiveData not called.

I tried to change the task to downloadTask

NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];
NSURLSessionDownloadTask * downloadTask =[defaultSession downloadTaskWithRequest:request];
[downloadTask resume];

It works with the download delegate, but data delegate (didReceiveData) not called.

Anybody can tell me what did I get wrong?

Forkey answered 23/8, 2014 at 12:52 Comment(0)
L
8

If you use the delegate-based rendition of NSURLSession, the NSURLSessionDataDelegate protocol includes a didReceiveData method, so you can instantiate a NSURLSessionDataTask and then write your own streaming code just like you would have with NSURLConnection:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self];
NSURLSessionTask *task = [session dataTaskWithRequest:request];
[task resume];

Alternatively, if you don't want to write your own streaming code, but want NSURLSession to stream this to a file for you and keep you informed of its progress, again, use the delegate based rendition of NSURLSession, create and resume a NSURLSessionDownloadTask:

NSURLSessionTask *task = [session downloadTaskWithRequest:request];
[task resume];

Having done that, you can then implement the didWriteData method of the NSURLSessionDownloadDelegate protocol and it will inform you as data is written (obviously, as long as your app is in the foreground; if you use background session and the app is not active, your app is only re-activated when all the background tasks finish). But that way you get the best of both worlds, where NSURLSession does a streaming download, but will keep you informed of its progress.

But, if you're using NSURLSessionDownloadTask, you don't have access to the NSURL of the temporary file until the download is complete (and in didFinishDownloadingToURL you would move this temporary file to its permanent final location).

Logan answered 23/8, 2014 at 13:20 Comment(5)
Thanks Rob for your quick reply. Sounds very good, I didn't know I could use dataTask to download file. Let me try and use the didReceiveData delegate method and get back to you. Thank you so muchForkey
Hi Rob, I tried and tried but couldn't get it to work. Could you please take a look at my EDIT and see if there's anything wrong I've done. Thanks.Forkey
@user1256663 And did you call that completionHandler block that didReceiveResponse provided to you? I know the first time I used delegate-based NSURLSession I completely glossed over that critical parameter: It won't continue until you call that completion block. Anytime any of these delegate methods provide completion block (received response, received challenge, handling redirect), you must call it.Logan
That was it! Thanks Rob. I have been pulling my hair for so long.Forkey
Thanks Rob, again. I was just searching the same topic and everything you wrote is correct. Unfortunatelly, dataTask can't be run in background (downloadTask can) ... so anyone reading this beware of this :)Andress

© 2022 - 2024 — McMap. All rights reserved.