NSURLDomainErrorDomain error -999 when app terminate with NSURLSession
Asked Answered
M

3

5

I have big trouble with NSURLSession when i'll terminate the App. I have downloaded the apple sample: https://developer.apple.com/library/ios/samplecode/SimpleBackgroundTransfer/Introduction/Intro.html

on Apple reference.

When i start download the file download correctly. When i enter in background the download continues to. When i terminate the application and i restart the app the application enter in:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error

And i catch this error:

The operation couldn't be completed. (NSURLErrorDomain error -999.)

It seems that i cannot restore download when app has been terminated. It's correct?For proceed with download i must leave application active in background?

Thank you Andrea

Maypole answered 15/10, 2014 at 16:9 Comment(0)
M
5

i insert this new lines of code:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    BLog();

    NSInteger errorReasonNum = [[error.userInfo objectForKey:@"NSURLErrorBackgroundTaskCancelledReasonKey"] integerValue];

    if([error.userInfo objectForKey:@"NSURLErrorBackgroundTaskCancelledReasonKey"] &&
       (errorReasonNum == NSURLErrorCancelledReasonUserForceQuitApplication ||
        errorReasonNum == NSURLErrorCancelledReasonBackgroundUpdatesDisabled))
    {
        NSData *resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData];
        if (resumeData) {
            // resume
            NSURL *downloadURL = [NSURL URLWithString:DownloadURLString];
            NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL];
            if (!self.downloadTask) {
                self.downloadTask = [self.session downloadTaskWithRequest:request];
                         }

            [self.downloadTask resume];
            if (!_session){
               [[_session downloadTaskWithResumeData:resumeData]resume];
                                         }
        }
    }
}

It catch NSURLErrorCancelledReasonUserForceQuitApplication but when the application try to [[_session downloadTaskWithResumeData:resumeData]resume]

reenter again in:

  • (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {

and give me again -999 error.

Maypole answered 16/10, 2014 at 15:8 Comment(1)
error: Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0xc7844f0 {NSUnderlyingError=0xc634c90 "bad URL", NSLocalizedDescription=bad URL} data: <> response: (null).you get this kind of error? or still -999?Kktp
P
8

A couple of observations:

  1. Error -999 is kCFURLErrorCancelled.

  2. If you are using NSURLSessionDownloadTask, you can download those in the background using background session configuration, e.g.

    NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:kBackgroundIdentifier];
    NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    

    If not using background session (e.g. you have to use data task, for example), you can use beginBackgroundTaskWithExpirationHandler to request a little time for the app the finish requests in the background before the app terminates.

  3. Note, when using background sessions, your app delegate must respond to handleEventsForBackgroundURLSession, capturing the completion handler that it will call when appropriate (e.g., generally in URLSessionDidFinishEventsForBackgroundURLSession).

  4. How did you "terminate the app"? If you manually kill it (by double tapping on home button, holding down on icon for running app, and then hitting the little red "x"), that will not only terminate the app, but it will stop background sessions, too. Alternatively, if the app crashes or if it is simply jettisoned because foreground apps needed more memory, the background session will continue.

    Personally, whenever I want to test background operation after app terminates, I have code in my app to crash (deference nil pointer, like Apple did in their WWDC video introduction to NSURLSession). Clearly you'd never do that in a production app, but it's hard to simulate the app being jettisoned due to memory constraints, so deliberately crashing is a fine proxy for that scenario.

Paraplegia answered 15/10, 2014 at 16:40 Comment(0)
M
5

i insert this new lines of code:

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    BLog();

    NSInteger errorReasonNum = [[error.userInfo objectForKey:@"NSURLErrorBackgroundTaskCancelledReasonKey"] integerValue];

    if([error.userInfo objectForKey:@"NSURLErrorBackgroundTaskCancelledReasonKey"] &&
       (errorReasonNum == NSURLErrorCancelledReasonUserForceQuitApplication ||
        errorReasonNum == NSURLErrorCancelledReasonBackgroundUpdatesDisabled))
    {
        NSData *resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData];
        if (resumeData) {
            // resume
            NSURL *downloadURL = [NSURL URLWithString:DownloadURLString];
            NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL];
            if (!self.downloadTask) {
                self.downloadTask = [self.session downloadTaskWithRequest:request];
                         }

            [self.downloadTask resume];
            if (!_session){
               [[_session downloadTaskWithResumeData:resumeData]resume];
                                         }
        }
    }
}

It catch NSURLErrorCancelledReasonUserForceQuitApplication but when the application try to [[_session downloadTaskWithResumeData:resumeData]resume]

reenter again in:

  • (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {

and give me again -999 error.

Maypole answered 16/10, 2014 at 15:8 Comment(1)
error: Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0xc7844f0 {NSUnderlyingError=0xc634c90 "bad URL", NSLocalizedDescription=bad URL} data: <> response: (null).you get this kind of error? or still -999?Kktp
M
1

I use this configuration

- (NSURLSession *)backgroundSession
{
/*
 Using disptach_once here ensures that multiple background sessions with the same identifier are not created in this instance of the application. If you want to support multiple background sessions within a single process, you should create each session with its own identifier.
 */
    static NSURLSession *session = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.example.apple-samplecode.SimpleBackgroundTransfer.BackgroundSession"];
        session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    });
    return session;
}

let me explain what i mean with "terminate the app" (in ios8):

  • double tap on home button
  • swipe on my open app.
  • app disappear from open app list
  • relaunch app.

When i reopen the app i enter into callback with error

The operation couldn't be completed. (NSURLErrorDomain error -999.)

There is something that i can't understand. This behaviour make me crazy! :-(

Maypole answered 15/10, 2014 at 21:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.