Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone willResignActive method doesn't complete execution

My app delegate needs to unlock/lock a purchase order on my microsoft SQL database when it enters the background or terminates.

Here's my code

    - (void)applicationWillResignActive:(UIApplication *)application {

    NSLog(@"App will enter background");
    if ([purchaseOrderIsLocked boolValue] && [purchaseOrderAutoID intValue] > 0) {
        NSLog(@"Unlock Purchase Order because app is in background %i", [purchaseOrderAutoID intValue]);
        [self unlockPurchaseOrderWithAutoID:self.purchaseOrderAutoID];
    }   

- (void)applicationWillEnterForeground:(UIApplication *)application {

   NSLog(@"App will enter foreground");

    if ([purchaseOrderIsLocked boolValue] == FALSE && [purchaseOrderAutoID intValue] > 0) {
        NSLog(@"Lock Purchase Order because app is coming back %i", [purchaseOrderAutoID intValue]);
        [self lockPurchaseOrderWithAutoID:self.purchaseOrderAutoID];
    }
}

-(void)lockPurchaseOrderWithAutoID:(NSNumber *)autoID {

NSLog(@"lock purchase order called with autoID=%i",[autoID intValue]);

    self.client = [SqlClientConnect connect];
    [self.client executeQuery:[NSString stringWithFormat:@"UPDATE PURCHASE SET PURCHASELOCK = '9999' WHERE PURCHASEORDERNO = '%i'", [autoID intValue]] 
          withCompletionBlock:^(SqlClientQuery *query) {

              if (query.succeeded) {
                  NSLog(@"locked purchase order");
                  purchaseOrderIsLocked = [NSNumber numberWithBool:YES];
              } else {
                  [self queryFailedWithError:query.errorText]; 
              } 
          }];
}

-(void)unlockPurchaseOrderWithAutoID:(NSNumber *)autoID {
    NSLog(@"unlock purchase order called with autoID=%i",[autoID intValue]);

    self.client = [SqlClientConnect connect];
    [self.client executeQuery:[NSString stringWithFormat:@"UPDATE PURCHASE SET PURCHASELOCK = '0' WHERE PURCHASEORDERNO = '%i'", [autoID intValue]] 
          withCompletionBlock:^(SqlClientQuery *query) {

              if (query.succeeded) {
                  NSLog(@"unlocked purchase order");
                  purchaseOrderIsLocked = [NSNumber numberWithBool:FALSE];
              } else {
                  [self queryFailedWithError:query.errorText]; 
              } 
          }];
   }

}

Okay it looks good to me... however when I run the app this is what I get from the log when I press the home button

    2011-12-14 13:41:20.558 MA Mobile[2267:707] App will enter background
    2011-12-14 13:41:20.558 MA Mobile[2267:707] Unlock Purchase Order
     because app is in background 18 

2011-12-14 13:41:20.559 MA Mobile[2267:707] unlock purchase order called with autoID=18

It should have gone all the way and posted "unlocked purchase order" but it doesn't When I resume the app this is what I get.

2011-12-14 13:41:44.741 MA Mobile[2267:707] App will enter foreground 1 2011-12-14 13:41:44.973 MA Mobile[2267:707] unlocked purchase order

It's like it runs the block code after resuming. Is this related to the block? Should I do something different?

like image 998
Hackmodford Avatar asked Feb 16 '26 06:02

Hackmodford


2 Answers

As soon as you pass off the block and return to -applicationDidResignActive:, your app is immediately suspended and the asynchronous call you started is essentially paused. You need to let the application know you need to spend more time in the background using -beginBackgroundTaskWithExpirationHandler:. You can do it with code like the example below. For more information on long running background tasks, see Background Execution and Multitasking in the iOS App Programming Guide.

This simple example shows how to use this feature in your code:

-(void)unlockPurchaseOrderWithAutoID:(NSNumber *)autoID
{
  NSLog(@"unlock purchase order called with autoID=%i",[autoID intValue]);

  // Start long-running background task
  UIBackgroundTaskIdentifier bti = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:NULL];

  self.client = [SqlClientConnect connect];
  [self.client executeQuery:[NSString stringWithFormat:@"UPDATE PURCHASE SET PURCHASELOCK = '0' WHERE PURCHASEORDERNO = '%i'", [autoID intValue]] withCompletionBlock:^(SqlClientQuery *query) {
    if (query.succeeded) {
        NSLog(@"unlocked purchase order");
        purchaseOrderIsLocked = [NSNumber numberWithBool:FALSE];
    } else {
        [self queryFailedWithError:query.errorText]; 
    }
    // After we complete the asynchronous block, we need to let the system know we can suspend now
    if( bti != UIBackgroundTaskInvalid )
      [[UIApplication sharedApplication] endBackgroundTask:bti];
  }];
}
like image 122
Jason Coco Avatar answered Feb 17 '26 19:02

Jason Coco


The applicationWillResignActive is very fast so it is likely that your task is not finishing before the application loses the foreground. This method is unlike some of the other methods that have similar names. The system is not asking you if it is OK for the application to resign, it is telling you that the application is resigning, now.

Look at the iOS Developer guide for the section on "Executing a Fininte Length Task in the Background" to see how you can let your task ask for extra time to complete.

like image 28
Walter Avatar answered Feb 17 '26 19:02

Walter



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!