[Résolu] NSUrlSession (iOS 7+) vs NSUrlConnection

Am_MeAm_Me Membre
septembre 2014 modifié dans API UIKit #1

Bonjour, à  tous


 


Voilà  ça fait un moment que je n'ai pas touché au développement iOS donc je suis un peu rouillé. J'ai cherché sur votre forum un "problème similaire" mais je n'ai rien trouvé.


 


Voilà  le fonctionnement de l'application :


En fait je suis en train de faire une application assez basique qui se connecte à  une page web, récupère un résultat (sous format xml) dans un NSData (à  travers NSUrlConnection ...). 


 


NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://monsitetoto.com/fichier.xml"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5];


   


NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];


 

Ma question est pour mon cas est-il plus pratique d'utilisé NSUrlSession ? Sachant que je n'ai pas besoin de login mot de passe pour afficher le .xml


Et quel sont les avantage et inconvénient si c'est utile ?


Réponses

  • AliGatorAliGator Membre, Modérateur
    Je remet le code ici mieux formatté, car dans ta question il n'est pas lisible.
    La prochaine fois pense à  utiliser les balises CODE dans ton post sur le forum pour encapsuler du code.

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@http://monsitetoto.com/fichier.xml] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:5];

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
  • AliGatorAliGator Membre, Modérateur
    septembre 2014 modifié #3
    Et sinon pour ta question :

    1) Malgré son nom qui peut porter à  confusion, NSURLSession n'a rien à  voir avec une session au sens web du terme, au sens "connecté avec une session utilisateur". Donc le fait que tu aies besoin d'un login / mdp ou pas pour accéder au XML n'entre nullement en jeu

    2) NSURLSession est le successeur de NSURLConnection. Les deux classes font dans l'ensemble la même chose, à  savoir envoyer des requêtes réseau et récupérer le résultat. NSURLConnection date des débuts de iOS, et existe donc depuis un bout de temps, alors que NSURLSession est un nouvel arrivant depuis iOS7, qui a pour objectif de supplanter NSURLConnection en proposant une nouvelle API un peu mieux pensée, plus flexible, et plus riche.

    Tout ce que tu peux faire avec NSURLConnection, tu peux le faire avec NSURLSession aussi. NSURLSession permettant de faire des choses en plus ou d'avoir + de finesse dans la configuration (politique de cache, download et upload de fichier/données en background même pendant que l'appli n'est plus lancée, etc) et propose aussi une API + moderne. Mais sinon dans l'ensemble c'est le même but.

    ---

    Du coup si ça marche avec NSURLConnection et que tu es déjà  habitué à  utiliser NSURLConnection, ce n'est pas gênant de continuer avec. Si tu veux en profiter pour migrer vers la nouvelle API, ça peut être l'occasion. Après tout transcrire ton code qui utilise NSURLConnection en du code utilisant NSURLSession à  la place n'est pas bien méchant.

    Au besoin je t'invite à  lire le URL Loading System Programming Guide for iOS qui explique tous les concepts liés à  NSURLSession (et à  NSURLConnection), comment l'utiliser, avec des exemples de code et tout. Tu as aussi ce tutoriel sur le site de Ray Wenderlich qui peut être une lecture plutôt instructive pour répondre à  ta question.
  • Ok encore merci parfaite explication ! :D


  • Am_MeAm_Me Membre
    septembre 2014 modifié #5

    Du coup je my prend bien là  ?



    NSURL *URL = [NSURL URLWithString:@www.toto.fr/file.xml];
    request = [NSURLRequest requestWithURL:URL];


    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request
    completionHandler:
    ^(NSData *data, NSURLResponse *response, NSError *error) {
    // ...

    NSString *resp = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@Recu %@",resp);
    }];

    [task resume];

    Car sur NSUrlConnection je passais par les méthodes :  



    - (void)connection:(NSURLConnection*)connection didReceiveData:(NSData *)data 


    - (void)connectionDidFinishLoading:(NSURLConnection*)connection

    , pour récupérer la data


  • AliGatorAliGator Membre, Modérateur
    Ah tu utilisais encore les delegates de NSURLConnection ?

    C'est possible hein et ça marche très bien, mais depuis il y avait la méthode avec les blocks [NSURLConnection sendAsynchronousRequest:queue:completionHandler:] qui était plus simple à  utiliser que de devoir toi-même concaténer les NSData au fur et à  mesure qu'elles arrivaient dans le delegate, donc déjà  même en continuant d'utiliser NSURLConnection, utiliser la méthode avec les blocks plutôt que le delegate t'aurait simplifié la vie.

    Et du coup si tu passes à  NSURLSession, c'est pareil, tu as le choix entre utiliser les méthode de delegate de NSURLSession ou utiliser l'API avec les blocks.
    On a tendance à  fortement préférer l'API avec les blocks dans la plupart des cas car elle est vraiment plus simple à  utiliser et que ça a tous les avantages des blocks (garder au même endroit dans le code l'envoi de la requête et le code à  exécuter lors de la réponse, plutôt que d'avoir à  scroller dans ton code source pour trouver la bonne méthode de delegate et d'éclater ton code en plein d'endroits différents ; faire de la capture automatique de variables ; etc).

    Or c'est ce que tu as fait dans ton code, donc c'est très bien, c'est bien comme ça qu'il faut faire. Limite tu as fait le pas de géant par rapport à  l'historique des API) en passant de NSURLConnection + delegate à  NSURLSession + blocks directement, sans passer par la case NSURLConnection + blocks ;)
  • Ahah ok cool ! 


     


    Merci pour ton explication AliGator :D au moins j'aurai appris 2 choses aujourd'hui 


     


    [Résolu]


  • Am_MeAm_Me Membre
    septembre 2014 modifié #8

    Oups voilà  j'ai une dernière question idiote comment je fais pour sauvegarder le NSData *data en dehors du bloc ???


    J'ai le message : Variable is not assignable


     


     


    MAJ


     


    J'ai réussi en faisant __block devant ma variable 



    __block NSData *theData = [NSData alloc];
        
        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                                completionHandler:
                                      ^(NSData *data, NSURLResponse *response, NSError *error) {
                                          // ...
                                          
                                          NSString *resp = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                                          NSLog(@Recu %@",resp);
                                          
                                          theData = data;
         
                                      }];
  • AliGatorAliGator Membre, Modérateur
    Bah sauf que pourquoi tu voudrais faire la sauvegarde en dehors du block?

    Si tu fais ça comme le code immédiatement après ton dataTaskWithRequest:... est exécuté immédiatement (alors que le block sera exécuté plus tard, quand la réponse à  la requête arrivera) bah ta variable theData va être nil pendant le temps où la requête attend la réponse (donc entre autres dans les lignes immédiatement après ton dataTaskWithRequest)
  • Am_MeAm_Me Membre
    septembre 2014 modifié #10

    Bah alors je dois avoir un problème de compréhension des sous-bloc.


     


    Voilà  comment je voudrais que l'application marche.


     


    1. 1 - Je lance ma requete
    2. 2 - Je récupère la data dans une variable maData
    3. 3 - Je passe à  NSXmlParser <- maData
    4. 4 - Je parse mon fichier
    5. 5 - Je traite l'information reçue

    Du coup j'ai du mal à  comprendre l'histoire du bloc. Car je bloque entre l'étape 2 et la 3


     


    Comment dois-je opérer la 3, 4 et 5 ? Et ou au final (dans le sous-bloc, autres ?)


  • Il faut juste comprendre que le traitement de la requête est asynchrone.


  • Ok ça je comprend. Ca fini quand ça veut et le code continue de tourner en attendant. Mais comment s'adapter du coup avec le bloc.


     


    Car avec les delegate ça se fait "automatiquement" mais c'est la première fois que je me mets au bloc et j'aimerai comprendre comment éviter les delegate et switcher sur un bloc


  • Delegate ou bloc le fonctionnement est le même.


    Soit il appelle une méthode du délégué, soit il appelle un bloc lorsque la requête est terminée.


    Si ça marche avec un délégué, il suffit grosso-modo de mettre le code de la méthode déléguée dans le bloc pour switcher vers un bloc.


  • Ah d'accord. Donc un bloc revient à  mettre une fonction dans une autre fonction (bon je me comprends).


    Du coup c'est une sorte de regroupement de code dans un même endroit et ça fait moins de travail pour aller chercher les méthodes delegate.


     


    Ok bah merci :)


  • jpimbertjpimbert Membre
    septembre 2014 modifié #15

    C'est ça.


    Il y a quelques petites différences qui rendent le bloc plus simple à  utiliser la plupart du temps.


    Par exemple, le bloc embarque les variables du contexte dans lequel il est déclaré (closure) alors que pour passer ces mêmes variables à  un délégué il faudrait les déclarer comme variables d'instance.


Connectez-vous ou Inscrivez-vous pour répondre.