L'application IOs7 plante en arrière-plan

Mon application se bloque parfois en arrière-plan et affiche le journal de plantage suivant:

Nov 7 12:33:31 iPad backboardd[29] <Warning>: MyApp[3096] has active assertions beyond permitted time: {( <BKProcessAssertion: 0x14680c60> identifier: Called by MyApp, from -[AppDelegate applicationDidEnterBackground:] process: MyApp[3096] permittedBackgroundDuration: 180.000000 reason: finishTask owner pid:3096 preventSuspend preventIdleSleep preventSuspendOnSleep )} 

En regardant à travers d'autres questions, j'ai découvert que le message d'erreur indique que je n'ai pas terminé une tâche correctement, donc quand son time a expiré le operating system l'a terminé et a écrasé mon application.

J'ai donc ajouté quelques NSLogs:

 - (void)applicationDidEnterBackground:(UIApplication *)application { [self saveContext]; [Settings setCallLock:YES]; [self saveStuff]; if ([self isBackgroundTaskNeeded]) { UIApplication* app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [self pauseDownloads]; NSLog(@"Debug - Ending background task %d",bgTask); [app endBackgroundTask:bgTask]; NSLog(@"Debug - Background task %d ended",bgTask); bgTask = UIBackgroundTaskInvalid; }]; NSLog(@"Debug - Starting background task %d",bgTask); [self initBackground]; } } 

et a découvert que la tâche a été appelée deux fois quand il s'est écrasé:

 Nov 7 12:30:02 iPad MyApp[3096] <Warning>: Debug - Starting background task 7 Nov 7 12:30:30 iPad MyApp[3096] <Warning>: Debug - Starting background task 8 Nov 7 12:33:26 iPad MyApp[3096] <Warning>: Debug - Ending background task 8 Nov 7 12:33:26 iPad MyApp[3096] <Warning>: Debug - Background task 8 ended Nov 7 12:33:26 iPad MyApp[3096] <Warning>: Debug - Ending background task 0 Nov 7 12:33:26 iPad MyApp[3096] <Warning>: Debug - Background task 0 ended 

Je n'étais pas capable de dire quand le double appel arrive et pourquoi. La question est donc de savoir pourquoi la tâche est appelée deux fois et y a-t-il un moyen de l'éviter?

Modifier:

 - (void) pauseDownloads { for (AFDownloadRequestOperation *operation in self.operationQueue.operations) { if(![operation isPaused]) { [operation pause]; } } } 

Vous devriez endBackground sans expiration.

  UIApplication* app = [UIApplication sharedApplication]; bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ [self pauseDownloads]; NSLog(@"Debug - Ending background task %d",bgTask); [app endBackgroundTask:bgTask]; NSLog(@"Debug - Background task %d ended",bgTask); bgTask = UIBackgroundTaskInvalid; }]; NSLog(@"Debug - Starting background task %d",bgTask); [self initBackground]; NSLog(@"Debug - Ending background task %d without expiration",bgTask); [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; 

Lorsque l'application entre au premier plan, mettez cet appel endBackgroundTask équilibrage –

 - (void)applicationWillEnterForeground:(UIApplication *)application { if (bgTask != UIBackgroundTaskInvalid) { NSLog(@"Debug - Ending background task %d without expiration (when applicationWillEnterForeground)",bgTask); [app endBackgroundTask:bgTask]; bgTask = UIBackgroundTaskInvalid; } // Also, to counter expiration handler pauseDownloads call, consider resuming the downloads here (or applicationDidBecomeActive app delegate). } 

Parce que – Le gestionnaire d'expiration {} est exécuté lorsque la tâche d'arrière-plan expire (généralement jusqu'à 10 minutes, mais pas garanti). Je suppose que votre tâche d'arrière-plan réelle est [self initBackground]; , sinon vous devriez le mettre en dehors du bloc et avant l'appel endBackgroundTask .

(Un autre problème potentiel)

En outre, j'ai remarqué votre code pauseDownloads maintenant, il semble que vous effectuez des téléchargements en utilisant NSOperationQueue lorsque l'application va en arrière-plan. Dans ce cas, veillez à ce que endBackgroundTask ne soit pas appelé tant que vous n'avez pas terminé le téléchargement ou l'exécution du gestionnaire d'expiration. En d'autres termes, le contrôle ne revient pas trop tôt, ce qui signifie que vous devrez peut-être surveiller ces NSOperation (s) de téléchargement.

La réponse courte est que votre accident se produisait parce que vous avez créé deux tâches de fond: 7 et 8, mais seulement terminé 8.

Avec cette connaissance, vous devez appliquer la solution d'Ashok pour vous assurer de toujours mettre fin à toute tâche de fond que vous créez.