Pedro
Pedro

Reputation: 507

iOS Background process

I need to make a synchronization with a server when my application is running. Sometimes this synchronization can take several minutes. On the iPhone this task is interrupted if the user press the home button or if the device does auto-lock.

I tried something like:

backgroundTaskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
            [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
            backgroundTaskID = UIBackgroundTaskInvalid;
    }];
[self Synchronization];

funcao sincronização:

-(void)Synchronization{

    object=nil;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [TheAppDelegate setSync:YES];

        send = NO;
        responseObj = [[ConteinerInicial alloc] init];
        object = [self fillObjectContainer:1];

        error = NO;

        [[objectManager HTTPClient] setDefaultHeader:@"Token" value:TheAppDelegate.token.token];
        [[objectManager HTTPClient] setDefaultHeader:@"Username" value:TheAppDelegate.token.userName];
        [[objectManager HTTPClient] setDefaultHeader:@"IDDevice" value:TheAppDelegate.token.IDDevice];

        [objectManager postObject:object path:@"" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *result){
            NSArray *response = [result array];
            NSLog(@"Loading mapping result: %@", result);

            NSDictionary *headerDictionary = [operation.HTTPRequestOperation.response allHeaderFields];
            NSString *authenticationStatus = [headerDictionary objectForKey:@"AuthenticationStatus"];

            // if server returns "NotAuthorized", user must login again
            if ([authenticationStatus isEqualToString:@"NotAuthorized"]) {
                [AppDelegate showErrorAlert:@"Login expired!"];
                [TheAppDelegate clearLoginToken];
                error = YES;
                return;
            }

            responseObj = [response objectAtIndex:0];

            if(responseObj.Package.count>0)
            {
                [self savePackage:responseObj tipo:1];
                [self Synchronization];
            }else
            {
                [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
                backgroundTaskID = UIBackgroundTaskInvalid;
            }

        } failure: ^(RKObjectRequestOperation *operation, NSError *reportError){
            RKLogError(@"Operation failed with error: %@", reportError);
            [AppDelegate showErrorAlert:@"There is some problem with the connection or the server! Please, check your connection or the address of the server and try again."];
            send = YES;
            [TheAppDelegate setSync:NO];
            error = YES;
        }];

    });
}

And at the end of synchronization is ready:

[[UIApplication sharedApplication] endBackgroundTask:backgroundTaskID];
                backgroundTaskID = UIBackgroundTaskInvalid;

but this code does not work, anyone have an idea how I can overcome this challenge?

The way to sync is to be asking for data until no longer exist. but with this code it just ends up in the backgroud object that is receiving at the time that goes into background

Upvotes: 1

Views: 1190

Answers (1)

Wain
Wain

Reputation: 119021

Your code is calling [self synchronization]; inside the expiration handler. That block is only called when your app runs out of time for running in the background. So you are trying to start your synchronisation only when there is no time left to do it.

Call [self synchronization]; outside of the block. The block should contain clean up / pause code and end the background task...

Also, look at using NSURLSession for good iOS 7 compatibility.

Upvotes: 3

Related Questions