3 votes

iOS : Pourquoi le dispatch_async vers le thread principal ne s'exécute-t-il pas lorsque l'état de l'application est UIApplicationStateBackground ?

J'ai récemment travaillé sur un projet qui implique la récupération de données en arrière-plan et j'ai remarqué que les blocs dispatch_async envoyés à la file d'attente principale ne s'exécutent pas.

Conditions d'essai : - L'application a des capacités de récupération en arrière-plan et de notification à distance. - Lancement via Scheme Configuré pour être lancé via Background Fetch sur un iPhone 6S Plus

Exemple de code :

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

     dispatch_async(dispatch_get_main_queue(), ^{
          NSLog(@"Won't run");
     });

      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

          NSLog(@"I ran");

          dispatch_async(dispatch_get_main_queue(), ^{
               NSLog(@"Won't run");
          });

          dispatch_sync(dispatch_get_main_queue(), ^{
               NSLog(@"Won't run");
          });
     });

     return YES;
}

Questions : 1) Quelqu'un sait-il pourquoi il en est ainsi ? Je ne trouve aucune documentation. Il est vrai que je cherche peut-être au mauvais endroit - jusqu'à présent, j'ai vérifié la documentation GCD sur dispach_async et j'ai fait quelques recherches approfondies sur le web. 2) Existe-t-il d'autres moyens (de préférence basés sur la GCD) de faire des appels asynchrones au thread principal, même en arrière-plan ?

Edit : performSelectorOnMainThread : ne semble pas fonctionner non plus.

0voto

jonschneider Points 150

Le problème semble être que je n'ai pas inclus la méthode de délégation application:performFetchWithCompletionHandler : dans mon AppDelegate. Pour une raison quelconque, le déclenchement d'une récupération en arrière-plan sans cette méthode implémentée bloque les distributions sur le thread principal.

0voto

Mijo Points 29

La solution pour moi a été de marquer le début de la tâche d'arrière-plan en appelant :

self.backgroundTask = [application beginBackgroundTaskWithExpirationHandler:^ {
        [application endBackgroundTask:self.backgroundTask];
        weakSelf.backgroundTask = UIBackgroundTaskInvalid;
    }];

et lorsque la tâche d'arrière-plan se termine, elle doit être équilibrée en appelant :

if (self.backgroundTask != UIBackgroundTaskInvalid) {
    [[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
    self.backgroundTask = UIBackgroundTaskInvalid;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X