Cache AFnetworking

Bonjour à  tous,



Je suis en train de regarder les frameworks qui pourraient remplacer ASI.

AFNetworking semble intéressant.



Par contre il semble qu'il existe des problèmes au niveau du cache.



Un exemple simple est de savoir si le cache à  été utilisé pour une requête ou non. Mes premiers tests ne m'ont pas permis de le savoir. Quelqu'un connait une solution simple avec ce framework ?



Ou bien recommandez vous un autre framework ?
Mots clés:

Réponses

  • AliGatorAliGator Membre, Modérateur
    Hello



    1) Quel est ton intérêt de savoir si une réponse vient du cache ou pas ?



    2) As-tu lu la FAQ ? Il y parle du cache. AFNetworking utilise le cache système, à  savoir NSURLCache. Rien ne t'empêche de le remplacer par un autre système de cache, comme il le suggère si tu veux du cache disque par exemple.



    En tout cas je ne recommande aucun autre framework que AFN. Rien vu de mieux jusqu'à  présent.
  • L'intérêt de savoir si les données viennent du cache , c'est pour savoir si j'ai besoin de faire un traitement (exemple: ajout de donnée dans le coredata) si le cache est utilisé alors je n'ai pas besoin de faire mon traitement.

    Je n'ai pas encore regardé la FAQ je vais jeter un oeil tout de suite.
  • La FAQ ne semble pas répondre à  mon besoin. Il montre comment utiliser un cache pour l'enregistrement sur le disque.
  • Je crois qu'il y a un problème de logique là .



    Qu'est-ce que tu entend par "si ça vient du cache, pas besoin de pousser des info dans CoreData" ?



    En toute logique ton contrôleur doit toujours lire tes données depuis CoreData à  travers ton DataProvider. C'est le DataProvider qui lui s'occupe d'aller chercher des infos de mise à  jour de base puis qui doit envoyer une notif en cas de MAJ faite.



    Dans cette orientation là  tu dois donc lorsque tu lance une synchro de base en background être capable de fournir le numéro de version de ta base / la date de dernière synchro pour que le serveur t'envois les différences.



    Le fait que cela viennent du cache iOS tu t'en fou totalement, tu ne devrais même pas avoir de cas où une réponse de ton API REST est ressorti du cache iOS (car cela voudrait dire que toi même tu as mal géré ton cache puisque tu redemande sur le réseau quelque chose que tu as déjà ).
  • hikoseihikosei Membre
    août 2012 modifié #6
    Je donne un exemple simple prenons un fichier xml qui serait récupéré en ligne , un fichier dont le traitement prend du temps.

    Il arrive parfois que modifier un fichier xml soit moins couteux pour une entreprise que développer un webservice complet.



    Dans ce cas, il est utile de savoir si les données récupérées viennent du cache ou bien si ce sont de nouvelles données. Ainsi on traite les données uniquement en cas de modification.
  • AliGatorAliGator Membre, Modérateur
    Bah dans ce cas il suffit de regarder les headers de la réponse, non ?

    Ou pour mon cas moi j'ai implémenté le système des ETags du standard HTTP/1.1 (car le serveur que j'interroge le supporte). C'est super simple à  coder dans ton code appelant la requête AFNetworking :
    • récupérer dans un NSDictionary (qui va te servir de catalogue de cache) le ETag associé à  ton URL, si tu en as un de stocké
    • envoyer la requête avec comme header "If-None-Match" la valeur du ETag (si présent)
    • lors de la réception de la réponse :
      • Si les données n'ont pas changées depuis que tu avais fait la requête, le ETag n'aura pas changé non plus et tu recevras un code retour 304 (Not Modified). Tu peux alors lire tes données depuis ton cache (et donc, dans ton cas, déjà  traitées).
      • Si les données ont changé, tu reçois les nouvelles données, avec un nouvel ETag. Tu traites alors ces nouvelles données, et tu mémorises le nouvel ETag pour le prochain coup.



    http://en.wikipedia.org/wiki/HTTP_ETag#Typical_usage



    Cet ETag sert donc de "hash"/"checksum" pour te permettre de ne demander les données au serveur que si elles ont changé. Cela correspond exactement à  l'usage que tu veux en faire de ton côté, à  savoir ne récupérer un XML que s'il a changé depuis la dernière fois. Et sinon, conformément au standard HTTP, te prendre un code de retour 304 Not Modified.





    En pratique ce n'est pas violent à  implémenter, je l'ai fait pour mon service de mon côté ça doit prendre genre 10 lignes max.
  • Merci je ne connaissais pas le système des ETags, je vais tester cette idée.

    ça devrait corriger mon problème.
  • Bonjour,

    confronté a un problème identique, j'ai fait quelques tests avec AFN.

    mon serveur me répond bien 304 lorsque je rafraichi ma page avec chrome. Mais avec AFNetworking j'ai toujours 200 en réponse.

    Il manque toujours l'equivalent de ASIHTTPRequest et de son "didUseCachedResponse" image/huh.gif' class='bbc_emoticon' alt='???' />
  • J'ai testé également malheureusement le serveur ne semble pas supporter les etag ...

    J'ai rencontré exactement le même problème que vassily. La valeur retournée est toujours 200 alors que dans chrome je vois bien 304.



    J'ai une idée je la présenterais demain j'ai pas le code sous les yeux.
  • vassilyvassily Membre
    août 2012 modifié #11
    'yoann' a écrit:


    Je crois qu'il y a un problème de logique là .



    Qu'est-ce que tu entend par "si ça vient du cache, pas besoin de pousser des info dans CoreData" ?



    En toute logique ton contrôleur doit toujours lire tes données depuis CoreData à  travers ton DataProvider. C'est le DataProvider qui lui s'occupe d'aller chercher des infos de mise à  jour de base puis qui doit envoyer une notif en cas de MAJ faite.



    Dans cette orientation là  tu dois donc lorsque tu lance une synchro de base en background être capable de fournir le numéro de version de ta base / la date de dernière synchro pour que le serveur t'envois les différences.



    Le fait que cela viennent du cache iOS tu t'en fou totalement, tu ne devrais même pas avoir de cas où une réponse de ton API REST est ressorti du cache iOS (car cela voudrait dire que toi même tu as mal géré ton cache puisque tu redemande sur le réseau quelque chose que tu as déjà ).




    Je n'ai pas forcement la main sur le serveur et donc ne peux pas implémenté ce type de cache.



    Le dataProvider doit commencer par faire une requete http pour savoir si les données distantes ont changées (ne telecharge que le header). Ca, AFNetWork le fait tres bien et me donne sa reponse en cache si il n'y a pas de changement.

    Seulement l'enregistrement en BDD n'est pas necessaire si cette response est la meme que lors du dernier appel.



    Obliger de stocker quelque par l'info comme quoi cette Request a été modifier a tel date et de comparer les dates lors d'un nouvel appel. C'est juste un peu lourd comme traitement et étonnant qu'on ne puisse pas avoir cette info de la part du URLConnection directement qui le sait déjà .
  • 'vassily' a écrit:


    Je n'ai pas forcement la main sur le serveur et donc ne peux pas implémenté ce type de cache.



    Le dataProvider doit commencer par faire une requete http pour savoir si les données distantes ont changées (ne telecharge que le header). Ca, AFNetWork le fait tres bien et me donne sa reponse en cache si il n'y a pas de changement.

    Seulement l'enregistrement en BDD n'est pas necessaire si cette response est la meme que lors du dernier appel.



    Obliger de stocker quelque par l'info comme quoi cette Request a été modifier a tel date et de comparer les dates lors d'un nouvel appel. C'est juste un peu lourd comme traitement et étonnant qu'on ne puisse pas avoir cette info de la part du URLConnection directement qui le sait déjà .






    Disons que le faire soit même permet de gérer un envois de diff et non de toute une base, question perf c'est mieux...





    Sinon regarde du coté de :

    [font=Courier, Consolas, monospace]- ([/font]NSCachedURLResponse[font=Courier, Consolas, monospace] *)connection:([/font]NSURLConnection[font=Courier, Consolas, monospace] *)[/font]connection[font=Courier, Consolas, monospace] willCacheResponse:([/font]NSCachedURLResponse[font=Courier, Consolas, monospace] *)[/font]cachedResponse
  • AliGatorAliGator Membre, Modérateur
    Heu en fait j'avais jamais trop cherché dans la doc ou le code quand j'ai lu la réponse, mais là  il se trouve que j'ai été faire un tour dans l'API de AFNetworking, et je vois une méthode
    - (void)setCacheResponseBlock:(NSCachedURLResponse * (^)(NSURLConnection *connection, NSCachedURLResponse *cachedResponse))block
    
    Ca ne solutionnerait pas ta question ?
Connectez-vous ou Inscrivez-vous pour répondre.