web-dev-qa-db-fra.com

performFetchWithCompletionHandler n'est jamais renvoyé

1) Ma configuration plist pour fournir le mode de fond:

<key>UIBackgroundModes</key>
<array>
    <string>fetch</string>
</array> 

2) Dans didFinishLaunchingWithOptions j'ai:

[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:1.0];

3) J'ai déclaré le protocole UIApplicationDelegate dans le délégué.

4) J'ai implémenté la méthode suivante, mais elle n'est jamais renvoyée. (Cela ne fonctionne que si je simule la récupération avec "XCode-> Debug-> Simulate Background Fetch".)

-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler

Pourquoi? S'agit-il d'une erreur bêta DP5? Dois-je enregistrer cela?

56
user2110287

Je crains que ce soit difficile à déboguer sur un appareil, car vous n'êtes pas sûr qu'il soit appelé dans le délai que vous spécifiez.

setMinimumBackgroundFetchInterval signifie qu'il n'est pas appelé dans un intervalle inférieur à la valeur que vous avez spécifiée. Mais il n'y a pas de setMaximumBackgroundFetchInterval. Donc, si iOS décide d'appeler votre application une seule fois par jour ou même une fois par semaine, elle ne sera pas appelée plus souvent, quel que soit votre minimumBackgroundFetchInterval. AFAIK iOS décide quand appeler performFetchWithCompletionHandler mesuré par le modèle quand et à quelle fréquence les utilisateurs démarrent l'application.

39
One Man Crew

En mode de débogage Xcode 5, vous pouvez forcer une extraction en arrière-plan à partir du menu: Débogage> Simuler une extraction en arrière-plan.

Ruff!

95
Clay Bridges

Il y a de nombreuses considérations:

  1. Assurez-vous que la capacité de récupération en arrière-plan a été définie dans le plist.

  2. Assurez-vous que la fonction de récupération en arrière-plan n'a pas été désactivée pour cette application particulière, ou en général, dans l'application Paramètres de l'appareil.

  3. Assurez-vous de définir l'intervalle de récupération minimum.

  4. Assurez-vous de quitter l'application avec élégance (par exemple, appuyez simplement sur le bouton d'accueil et lancez une autre application et/ou verrouillez simplement l'appareil). Mais si vous tuez l'application (en appuyant deux fois sur le bouton d'accueil et en glissant vers le haut, ou quoi de plus), cela empêchera le système d'exploitation d'offrir à votre application une chance de déclencher les demandes de récupération en arrière-plan suivantes (au moins jusqu'à ce que l'utilisateur exécute à nouveau l'application) ).

  5. Assurez-vous de tester cela sur un appareil physique et de ne pas exécuter l'application via le débogueur Xcode. Le fait d'être attaché au débogueur modifie le comportement des opérations en arrière-plan.

  6. Assurez-vous que l'application effectue effectivement des requêtes réseau. Si vous avez une application qui n'effectue aucune requête réseau, elle ne participera pas à la récupération en arrière-plan. Si vous faites, par exemple, une petite application de test avec "extraction en arrière-plan" et n'émettez aucune demande réseau, vous ne participerez pas à l'extraction en arrière-plan.

    De même, si le système d'exploitation démarre votre application en mode arrière-plan afin de pouvoir effectuer une récupération en arrière-plan, si vous n'effectuez pas réellement une demande réseau, le système d'exploitation peut cesser d'offrir à votre application la possibilité d'effectuer des récupérations en arrière-plan à l'avenir.

  7. Assurez-vous d'appeler le gestionnaire d'achèvement, et faites-le dans le temps imparti, sinon votre application pourrait ne pas participer à la récupération en arrière-plan à l'avenir.

  8. Le moment auquel le système d'exploitation effectue la récupération en arrière-plan est dicté par des règles mal documentées qui peuvent changer à l'avenir. Mais les facteurs pertinents incluent:

    • Si l'appareil est connecté à l'alimentation et/ou est suffisamment chargé;

    • Qu'il soit connecté au WiFi ou non;

    • La fréquence à laquelle l'utilisateur lance réellement l'application;

    • Si l'appareil effectue d'autres tâches liées au réseau (par exemple, si la récupération en arrière-plan peut être fusionnée avec d'autres opérations réseau);

    • La fréquence à laquelle les demandes de récupération en arrière-plan ont entraîné la disponibilité de données.


    D'après mon expérience, après que l'application soit exécutée la première fois, si elle est connectée au wifi et à l'alimentation, si vous réveillez l'appareil environ 5 minutes plus tard, l'application effectuera une récupération en arrière-plan. Ce n'est pas une règle stricte et rapide, mais juste ce que nous avons vécu dans le passé.

    Mais de nombreux nouveaux développeurs publient sur Stack Overflow avec des questions telles que "comment puis-je avoir des données de demande d'application jamais x minutes (ou heures)", "comment puis-je demander des données tous les jours à 2 heures du matin", etc. La réponse courte est que vous ne pouvez pas. Le système d'exploitation décide du moment des antécédents à sa seule discrétion. Vous ne pouvez pas contrôler cela (autre que l'intervalle de demande minimum; mais vous ne pouvez pas contrôler l'intervalle maximum, car le système d'exploitation le contrôle).

  9. Cela peut sembler évident pour beaucoup, mais assurez-vous d'avoir un moyen fiable de savoir si le processus de récupération en arrière-plan fonctionne correctement ou non. Le cadre des notifications utilisateur peut être utilisé pour présenter une alerte afin que vous sachiez si la demande d'arrière-plan a entraîné quelque chose. Alternativement, os_log Les "notifications unifiées" peuvent être utilisées pour publier des messages sur l'appareil qui peuvent être surveillés sur l'application macOS Console. Mais plus d'une fois, j'ai vu des utilisateurs faire quelque chose comme attendre que le message apparaisse dans Xcode ou attendre UIAlertController. Vous avez besoin d'un mécanisme qui fonctionne lorsqu'il n'est pas connecté à Xcode et lorsque l'application ne passe jamais au premier plan.

23
Rob

(Cela ne fonctionne que si je simule la récupération avec "XCode-> Debug-> Simulate Background Fetch".)

C'est parce que vous êtes en mode débogage. Veuillez essayer de lancer l'application sans XCode.

21
user1700099

En utilisant votre appareil, vous pouvez tirer application:performFetchWithCompletionHandler avec les étapes suivantes:

  • Mettez votre application en arrière-plan
  • Verrouillez votre appareil et attendez 5 minutes.
  • Déverrouillez votre appareil, cela déclenchera la méthode
21
user2936585

Une autre chose à vérifier est votre fichier plist. Assurez-vous que la touche UIApplicationExitsOnSuspend n'est pas présente.

De nombreuses personnes ici sur Stack Overflow ont recommandé d'utiliser ce paramètre pour forcer votre application à redémarrer chaque fois qu'elle est lancée. Cela fonctionne, mais l'effet secondaire est qu'il empêche le déclenchement de la nouvelle fonction de récupération d'arrière-plan iOS 7.

5
Axeva

Si application: performFetchWithCompletionHandler: ne se déclenche jamais (sauf si vous le simulez à l'aide de Xcode), vérifiez également si la préférence "Actualisation de l'application en arrière-plan" est "Activé" pour votre application. (Application Paramètres -> Général -> Actualisation de l'application en arrière-plan)

2
Anastasia

En outre, la récupération en arrière-plan est désactivée si l'iPhone est en mode basse consommation.

2
adrian1kat

Apple fournit un algorithme qui définit la fréquence de déclenchement de la récupération en arrière-plan, en fonction de votre propre utilisation de l'application. Si vous l'utilisez beaucoup, il sera récupéré aussi souvent que possible, mais si vous utilisez comme à 16 h tous les jours, la récupération en arrière-plan devrait se déclencher juste avant, de sorte que vos données soient mises à jour lorsque vous la lancez. Référer ceci lien

1
CrazyDeveloper