AFNetwoking et backgroundSession (question diverse)

Bonsoir à  tous


 


Je suis en cours d'implémentation de AFNetworkin 2.0 pour utiliser NSURLSession et le téléchargement en background.


 


J'ai étudié les différents tutoriel (http://code.tutsplus.com/tutorials/working-with-nsurlsession-afnetworking-20--mobile-22651 notamment), mais j'ai malgré tout plusieurs questions :


 


1) Kill de l'application


 


Question simple : lorsque l'application est tuer (pas juste passer en background, mais vraiment killer) j'ai compris que le téléchargement en background se continuai tout de même, est-ce bien ça ? (histoire d'être sur)


 


Problème : Mon chef de projet me dis que ce n'est pas le comportement attendus (pour lui, kill de l'application = annulation des téléchargements en cour), du coup y a t'il un moyen d'annuler un téléchargement lors du kill d'une application ? (j'y crois pas trop...)


 


2) downloadTaskDidFinishDownloading


 


Dans la fonction downloadTaskWithRequest:progress:destination:completionHandler:, il y a le warnig suivant (dans AFURLSessionManager) :



If using a background NSURLSessionConfiguration on iOS, these blocks will be lost when the app is terminated. Background sessions may prefer to use setDownloadTaskDidFinishDownloadingBlock: to specify the URL for saving the downloaded file, rather than the destination block of this method.



 


Or, si je suis les différent appel de fonction, je constate que downloadTaskDidFinishDownloading est bien setter (addDelegateForDownloadTask:progress:destination:completionHandler:) par le block 'destination', donc pourquoi ce warning ?


 


3) NSDictionnary userInfo


 


Dans AFURLConnectionOperation, j'utilise souvent le dictionnaire userInfo pour transférer au block de réponse des informations relative au fichier téléchargé (son id, type de file spécifique à  l'app, etc.), hors ce dictionnaire n'est pas disponible avec AFURLSessionManager et NSURLSession ; que pourrais-je utiliser en remplacement ?


 


4) responseString et responseData


 


dans AFURLConnectionOperation, j'utilise souvent les fonctions responseString et responseData. Y a t'il des fonctions similaire dans AFURLSessionManager ou NSURLSession ?


 


Merci de vos réponse.


 


D.H.


 

 


 


 


Réponses

  • AliGatorAliGator Membre, Modérateur

    3) Pourquoi ne pas utiliser le fait que les blocks capturent automatiquement les variables externes qu'ils utilisent (concepts de "closures") ? Du coup plus du tout besoin de passer tes données par userInfo, tu les mets juste directement dans le code du bloc et elles sont capturées


     


    https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html#//apple_ref/doc/uid/TP40011210-CH8-SW3


  • septembre 2014 modifié #3

    1/ et applicationWillTerminate ???


     


    (Dans le AppDelegate)

  • AliGatorAliGator Membre, Modérateur


    1/ et applicationWillTerminate ???

    (Dans le AppDelegate)

    cette méthode n'est jamais appelée sur iOS sauf si tu as activé la clé / le mode UIAppExitOnSuspend (ce que quasiment personne ne fait de nos jours ça serait dommage en terme d'UX)


    Par contre dans le applicationDidEnterBackground tu peux annuler tes requêtes par exemple (cf la doc de NSURLSession pour les méthodes d'annulation, et le URL Loading Programming Guide pour la mécanique générale et les détails sur le download en tâche de fond et tout)


    Mais bon un utilisateur n'est pas sensé killer volontairement une appli. Et les Guidelines iOS (et le bon sens en terme d'UX) suggèrent que quel que soit le cas (genre l'utilisateur a passé l'app en background mais plus tard iOS qui avait besoin de mémoire a pris sur lui de killer l'appli) il faut que l'utilisateur ait l'impression que l'appli n'ait jamais été tuée et restaurer l'état.


    Donc c'est pas logique (perso ça m'énerverait si une app faisait ça) d'arrêter le download si jamais l'utilisateur est juste allé voir ses mails et lancé un petit jeu en attendant que le download se termine, et que pendant ce temps (où l'appli était vivante mais en background) iOS réclame de la RAM (genre car le jeu est un peu consommateur) et kill ton appli pour en réclamer un peu. Du coup tu finis ton jeu tu retournes dans l'appli pour voir où en est le download et là ... tu te rends compte qu'il a été annulé parce que l'app à  été tuée par iOS ? C'était bien la peine d'attendre 30mn en jouant si ton appli s'est faite killé au bout de 5mn passé sur ton jeu gourmand en RAM pour s'apercevoir qu'il faut relancer le download...



    Une appli qui a ce comportement et ce fonctionnel moi c'est poubelle direct. Trop frustrant et inutilisable si au final pour être sur que le download soit pas annulé t'es obligé de rester dans l'appli de peur qu'elle soit killé par iOS sinon, et du coup pendant le download tu je peux rien faire... génial...
  • Ah ben merci de cette précision. Je comprends mieux maintenant pourquoi les différents essais restés lettre morte.


    Pourquoi est-elle toujours présente par défaut alors ? (simple question)


  • AliGatorAliGator Membre, Modérateur
    C'est vrai qu'il serait temps qu'Apple l'enlève de ses templates de projet cette méthode !
  • Merci pour ses réponses.


     


    Pour la question 1), je suis d'accord avec toi AliGator, mais le patron à  décider que ce n'était pas le comportement normal.......... Je vais avoir du boulot.


     


    Pour le 3) et 4), je vais voir ce que je peux faire en utilisant les variables externe dans un block.


     


    Sinon, auriez vous des information concernant le point 2) ?


  • AliGatorAliGator Membre, Modérateur
    septembre 2014 modifié #8


    Pour la question 1), je suis d'accord avec toi AliGator, mais le patron à  décider que ce n'était pas le comportement normal.......... Je vais avoir du boulot.




    Change de patron.


     


    Ou explique lui comment ça marche iOS (que iOS peut killer une appli en bkg sans te prévenir, etc)


  • Y a un truc qui m'échappe :


     


    J'ai télécharger le projet exemple d'Apple (Simple Background Transfer) et lorsque je kill l'application, je vois dans mon proxy charles que le téléchargement se stop !


     


    Pourquoi le téléchargement en background ne fonctionne pas, même dans le projet exemple d'Apple ?


  • samirsamir Membre
    septembre 2014 modifié #10


    Donc c'est pas logique (perso ça m'énerverait si une app faisait ça) d'arrêter le download si jamais l'utilisateur est juste allé voir ses mails et lancé un petit jeu en attendant que le download se termine, et que pendant ce temps (où l'appli était vivante mais en background) iOS réclame de la RAM (genre car le jeu est un peu consommateur) et kill ton appli pour en réclamer un peu. Du coup tu finis ton jeu tu retournes dans l'appli pour voir où en est le download et là ... tu te rends compte qu'il a été annulé parce que l'app à  été tuée par iOS ? C'était bien la peine d'attendre 30mn en jouant si ton appli s'est faite killé au bout de 5mn passé sur ton jeu gourmand en RAM pour s'apercevoir qu'il faut relancer le download...

     




     


    En te lisant @Aligator  j'ai compris que une application killé par le système iOS ou bien par l'utilisateur lui même continue tout de même les téléchargement en cours ?


     


    Ce que j'ai compris dans la documentation c'est que si l'application est "killé" c'est tous les téléchargements qui vont être annulés. ( ce qui est logique aussi puisque l'application n'est plus en RAM).


     


     Et pire encore même les push silencieux et les téléchargement périodiques en arrière plan ne vont plus réveiller l'application. Il faudra relancer l'application pour réactiver tout ça.




  • Y a un truc qui m'échappe :


     


    J'ai télécharger le projet exemple d'Apple (Simple Background Transfer) et lorsque je kill l'application, je vois dans mon proxy charles que le téléchargement se stop !


     


    Pourquoi le téléchargement en background ne fonctionne pas, même dans le projet exemple d'Apple ?




     


    C'est le comportement normal. Si tu kill l'application les téléchargement vont être annulés, par contre (normalement??) t'auras un callback pour t'informer de cet évènement. 

  • Voila la


     




    C'est le comportement normal. Si tu kill l'application les téléchargement vont être annulés, par contre (normalement??) t'auras un callback pour t'informer de cet évènement. 




    Voila le hic !


     


    Je n'ai aucun callback appeler au moment du kill.


    Comme je ne sais pas où a été stocké le fichier temporaire, la reprise va être coton...


  • AliGatorAliGator Membre, Modérateur
    ça dépend le type de session que tu utilises aussi ! Si c'est une backgroundSession et que tu demandes une downloadTask c'est le système qui la prend en main et donc continue sa vie indépendamment de l'appli (donc même quand l'appli est tuée, je pense, bien que je n'ai pas testé c'est ce que j'attendrais comme comportement)
  • @Aligator c'est absolument ça, j'ai pas testé mais je viens de consulter la doc et ça confirme ce que tu dis. Finalement le système crée des processus séparé pour les "backgroundTask" et si l'application est suspendue ou terminée, le système continue la tache et rêve!llera l'application à  la fin ( d'au moins ce que j'ai compris :)).


     


    Voila le lien de la doc pour plus d'infos :


     


    https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html


  • @AliGato et Samir


    Malheureusement, ce n'est absolument pas ce que je constate en test avec l'application Démo d'Apple :


    Application suspendu : le téléchargement continue


    Application terminée : le téléchargement est annulé


     


    Pourtant le documentation Apple dit :


    Apps that initiate downloads in the foreground can hand off management of those downloads to the system, thereby allowing the app to be suspended or terminated while the download continues.

     


    MAIS Voici la ligne importante :


    When all of the tasks associated with a background session are complete, the system relaunches a terminated app (assuming that the sessionSendsLaunchEvents property was set to YES and that the user did not force quit the app)

     


    Donc le téléchargement en background différencie l'application éteinte suite problème mémoire et éteinte suite action utilisateur !


     


    Je sens que ça va pas être simple !

  • Ah ! la documentation est claire dans ce cas.


     


    Si c'est le système qui "kill" l'application, dans ce cas il va continuer le process de la session et réveillera l'application à  la fin.


    Dans le cas ou c'est l'utilisateur qui a "killé" l'application, ben le système annule tout :).


     


    C'est un peu gênant et en même temps logique. ça m'arrive de "killé" mes application encensant que je vais ganger de la batterie ( choses qui est fausse !) donc je mis fin à  toute tache éventuelle ou mise à  jour en background des application sans le savoir.




  • Si c'est le système qui "kill" l'application, dans ce cas il va continuer le process de la session et réveillera l'application à  la fin.


    Dans le cas ou c'est l'utilisateur qui a "killé" l'application, ben le système annule tout :).




     


    Je sais pas comment tester ça. Sur simulateur, on peut provoquer un memory warning, mais est-ce que l'on simuler une fermeture d'application provoquer par l'os ?


     


    Si on ne peux pas le tester, le dev va pas etre simple.

  • AliGatorAliGator Membre, Modérateur
    Je ne crois pas qu'il y ait de façon toute faite proposée par le simulateur.
    Tu peux killer l'application, de la même façon que tu le ferais sur device (double-clic sur bouton Home, swipe de l'app vers le haut), ce qui va bien sûr du coup te faire arrêter l'application avec un signal "SIGKILL" (et ton Xcode va s'arrêter dans le main() en te disant qu'il a reçu un signal de kill, effectivement), tu peux générer un memoryWarning, mais je ne crois pas que tu puisses simuler un kill généré par l'OS.

    Par contre je crois qu'il y en a qui ont feinté. Genre ils ont créé un projet Xcode pour faire une appli bidon avec un bouton et quand on clique dessus ça consomme une quantité astronomique de mémoire inutilement (genre une boucle "for" qui crée un packet d'objets volumineux et les garde tous en mémoire). Du coup ensuite quand ils lancent leur vraie app, pour tester le kill par l'OS ils basculent ensuite sur cette app bidon, ils cliquent sur le bouton pour consommer un max de RAM, et normalement au bout d'un moment ça va donc déclencher un kill de la vraie app par iOS qui va avoir besoin de RAM pour l'app bidon qui est au premier plan.

    Sauf que j'ai pas testé de mon côté, mais je pense que cette bidouille / astuce n'est valable que sur device, où la RAM est effectivement assez limitée, car sur simulateur c'est la RAM du Mac qui est sollicitée, et du coup t'as vachement + de marche avant d'arriver à  expiration de la RAM (et en + si tu bouffes toute la RAM de ton Mac, il risque de swapper plutôt que de remonter au simulateur qu'il n'a plus de RAM, et de toute façon ton Xcode qui lui tourne sur le Mac donc a besoin aussi de la RAM du Mac se mettrait à ... ramer justement, ... bref pas top)
  • Est-ce que quelqu'un aurai un exemple d'application consommatrice de RAM ?


     


    J'ai une autre question concernant NSURLSession et AFURLSessionManager :


    Si j'ai plusieurs téléchargement à  effectué en même parallèle, est-ce que je dois créer un AFURLSessionManager pour téléchargement ou réutiliser le même en lui ajoutant de nouveaux download ?


  • CéroceCéroce Membre, Modérateur

    Est-ce que quelqu'un aurai un exemple d'application consommatrice de RAM ?


    malloc(500e6);
Connectez-vous ou Inscrivez-vous pour répondre.