5

Some background first: Application is supposed to grab files from AWS S3 server. In order to do that, first step of that process is to go to local server and get the name of the file and some other information from it. After that step we have a complete URLMutableRequest.

NOTE: I am setting up the NSURLSession as a background session:

- (NSURLSession *)backgroundSession
{
    static NSURLSession *session = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"identifier"];
        session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    });
    return session;
}

This is the task to download the files from AWS S3 server:

for this task I want to use the delegates to run in background mode.

@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
@property (nonatomic, strong) NSURLSession *defaultSession; 

self.defaultSession = [self backgroundSession];
self.downloadTask = [self.defaultSession downloadTaskWithRequest:request];
[self.downloadTask resume];

How to I get a RESPONSE form this REQUEST?

Apple documentation says you can't have a block as completionHandler when using a backgroundSessionConfiguration.

casillas
  • 16,351
  • 19
  • 115
  • 215
wagppinto
  • 75
  • 1
  • 9

3 Answers3

7

In case anyone wondering how to get download response before download is complete, try this: fire off dataTask instead, get the response, then convert dataTask to download if required.

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

NSURLSessionDataDelegate

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
    // use response, convert data task to download task
    completionHandler(NSURLSessionResponseBecomeDownload);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask {
    // downloadTask converted from dataTask
}

NSURLSessionDownloadDelegate

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    // update progress
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    // copy downloaded file from location
}
Roman B.
  • 3,598
  • 1
  • 25
  • 21
1

NSURLSessionDownloadTask has a response property (part of its base class, NSURLSessionTask) that should be set to the response. See here.

Mean Dinosaur
  • 376
  • 1
  • 12
  • so, if using the exemple in my description, if I use `self.downloadTask.response` I should be able to get the **response** from the given request? – wagppinto Sep 11 '15 at 19:44
  • Yes. If you hold a reference to the `NSURLSessionDownloadTask`, you can access its `response` property any time after it has completed. – Mean Dinosaur Sep 11 '15 at 20:37
  • If you are implementing the delegate method `-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error`, it will be available from the `task` passed to you at that time. – Mean Dinosaur Sep 11 '15 at 20:44
  • If you're looking to handle something like a 404, you need to have a look at Roman B.'s answer because the response property of the downloadTask object will not do. – Julius Aug 03 '17 at 16:55
  • If you did a HTTP request, you can cast the response into a NSHTTPURLResponse as per https://developer.apple.com/documentation/foundation/nsurlresponse?language=objc like this ` ((NSHTTPURLResponse*)downloadTask.response).statusCode`. – bk138 Oct 12 '18 at 11:47
0

You need to implement the NSURLSessionDownloadDelegate protocol in your class (since you specified the sessions delegate as self).

You should check the docs for the available methods, but you're going to implement at least the following :

- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
deadbeef
  • 5,409
  • 2
  • 17
  • 47
  • I am implementing the delegates methods. I am moving the file form temp location to destination location and verifying when `URLSession:task:didCompleteWithError` is called. But **how to get the response from the request** ??? =] – wagppinto Sep 11 '15 at 19:16
  • You mean the http headers and stuff ? Check @mean-dinosaur answer, use the response property (you might need to cast it to a `NSHTTPURLResponse` – deadbeef Sep 11 '15 at 19:50
  • Ok! I need to convert this response to `NSString *downloadString = [[NSString alloc]initWithData:downloadData encoding:NSUTF8StringEncoding];` to **initWithData** any suggestion on how to cast to `NSHTTPURLResponse` and get `NSData`??? @mean-dinosaur – wagppinto Sep 11 '15 at 20:30
  • What do you want exactly in terms of data ? And what do you think the response (or what you call the **response**) is or should be ? – deadbeef Sep 11 '15 at 20:32
  • If you want the content of your file (the data), then you will get it with the delegate methods. If you want the metadata (http headers of the response for example), then use the response property. – deadbeef Sep 11 '15 at 20:35