[Objective-c + JSON-RPC] Discuter avec un serveur

2»

Réponses

  • C'est ce que je ne comprend pas, l'affectation une fois faite, j'arrive à  l'afficher à  l'intérieur de mes blocks, mais qu'on j'essaye de les afficher à  l'extérieur, il veut pas.





    JSONRPCService * service = /color][color=#578187]JSONRPCService[/color][color=#000000] [/color]serviceWithURL[color=#000000]:serviceURL [/color]version[color=#000000]:[/color]JSONRPCVersion_2_0[color=#000000;


    service [color=#38595d]callMethodWithNameAndParams[/color]:[color=#c72c25]@"login"[/color], [color=#b41ca4]self[/color].[color=#7134aa]log[/color], [color=#b41ca4]self[/color].[color=#7134aa]pwd[/color], [color=#b41ca4]nil[/color completion:^(JSONRPCMethodCall * methodCall,id result,NSError * error)

    {

    NSArray * tab = [/color][color=#7134aa]NSHTTPCookieStorage[/color][color=#000000] [/color]sharedHTTPCookieStorage[color=#000000 cookiesForURL:service.serviceURL];


    int i=[tab count];

    for(int j=0;j<i;j++)

    {

    NSHTTPCookie * Cookie;

    Cookie = [tab objectAtIndex:j];

    if (Cookie [color=#401082]name[/color isEqualToString:@VHTSESSION])

    {

    NSLog(@cookie1: %@",[Cookie value]);

    valCookie=[Cookie value];

    NSLog(@cookie2: %@",valCookie);

    service [color=#38595d]callMethodWithNameAndParams[/color]:[color=#c72c25]@&quot;get_token&quot;[/color], [color=#b41ca4]nil[/color completion:^(JSONRPCMethodCall * methodCall,id result,NSError * error)

    {

    NSLog(@token1: %@",result);

    valToken=result;

    NSLog(@token2: %@",valToken);

    }

    ];

    }

    }

    }

    ];

    NSLog(@cookie3: %@, token3: %@",valCookie,valToken);






    Voila le résultat:





    2012-04-17 15:59:25.051 vht2[1677:f803] cookie3: (null), token3: (null)

    2012-04-17 15:59:25.329 vht2[1677:f803] cookie1: cfi9sitr1bs34vhph2fudlaih6

    2012-04-17 15:59:25.330 vht2[1677:f803] cookie2: cfi9sitr1bs34vhph2fudlaih6

    2012-04-17 15:59:25.373 vht2[1677:f803] token1: 95bca9100c2794a7f34ef67ebbb26555

    2012-04-17 15:59:25.374 vht2[1677:f803] token2: 95bca9100c2794a7f34ef67ebbb26555





    image/huh.gif' class='bbc_emoticon' alt='???' /> Ais-je mal fait mes affectations ?
  • AliGatorAliGator Membre, Modérateur
    Ah mais oui mais ce que tu n'as pas tilté c'est que tout ça est asynchrone en fait ! (Et encore heureux d'ailleurs, si ton appli était "gelée" pendant les deux requêtes à  ton serveur, l'utilisateur penserait que ton app serait plantée pendant les quelques secondes pendant lesquelles les requêtes s'exécuteraient...)



    Excuse moi de t'avoir induit en erreur en te proposant la solution avec __block en fait, mais il faut donc savoir que JSON-RPC comme la plupart des frameworks qui traitent avec le réseau fonctionnent de façon asynchrone : ils envoient la requête, et ils te préviennent "plus tard", quand la réponse sera arrivée (qui selon l'état de ton réseau sur l'iPhone peut prendre quelques secondes), avec le bloc que tu mets en "completion".

    Donc ce bloc dans "completion" est exécuté quand tu auras la réponse (un peu comme avec le mécanisme de delegate où les méthodes de delegate sont appelées "plus tard") et pas immédiatement quand tu appelles login. Et forcément ta méthode login ne peut pas directement retourner ton NSArray avec valCookie et valToken, puisqu'à  la fin de la méthode "login", la requête a été envoyée, mais la réponse n'est certainement pas encore reçue de ton serveur JSON-RPC. Il faut donc que tu prévois un mécanisme asynchrone (delegate, completionBlock, notification, ...) pour te prévenir de façon asynchrone quand tu auras la réponse qui peut intervenir plus tard.
  • D'accord je comprend mieux, au gros faudrait que après ma complétion, je dois avoir quelque chose qui puissent attendre que le serveur est bien répondu. L'idéal serait que tout cela soit gérer dans ma méthode login.

    Pourquoi pas un mécanisme asynchrone et l'idéal serait avec complétionBlock.

    :/

    Etant peu aboutit en objective-C, voudrais-tu bien me donner un coup de main image/huh.gif' class='bbc_emoticon' alt='???' /> Sachant que le squelette de cette méthode "login" sera à  l'identique, car pour le suite de mon appli, j'enverrais d'autre requête JSon-Rpc.



    En attendant je suis bloqué
  • AliGatorAliGator Membre, Modérateur
    avril 2012 modifié #35
    Bah vu que ta procédure de login est asynchrone par essence, tu n'as pas le choix d'avoir le squelette de ta méthode login qui retourne tout de suite, et une autre méthode appelée (completion, delegate, ...) quand le login aura la réponse. Car si tu ne fais pas ça, ton application va bloquer le temps que ta requête soit envoyée puis reçoive la réponse, ça va complètement geler ton application pendant plusieurs secondes, la laissant comme si elle était plantée, sans pouvoir rien faire.



    Si tu n'es pas encore à  l'aise avec les blocks et surtout avec comment déclarer une méthode de login qui prennd des completionBlocks etc, tu peux le faire avec la méthode des delegates dans un premier temps, si c'est plus lisible pour toi :


    -(void)login<br />
    {<br />
      // ...<br />
      [[service callMethodWithNameAndParams:@&quot;get_token&quot;, nil] completion:^(JSONRPCMethodCall * methodCall,id result,NSError * error)<br />
      {<br />
    	valToken=result;<br />
    	[self userDidLoginWithCookie:valCookie andToken:valToken];<br />
      }];<br />
    }<br />
    <br />
    -(void)userDidLoginWithCookie:(NSString*)cookie token:(NSString*)token<br />
    {<br />
      // Ici tu traites la réponse à  ta méthode de login que ton WebService t&#39;aura renvoyé... plus tard (le temps que la requête soit envoyée, la réponse soit reçue, etc)<br />
    }
    
  • Ok d'accord, du coup j'ai fait comme tu m'as dit:









    - (void) login

    {

    NSString * http=@"http://";;

    NSString * suite=@/auth/rpc.php;


    NSString * lien=[NSString stringWithFormat:@%@%@%@",http,self.adre,suite];

    NSURL * serviceURL = [NSURL URLWithString:lien];

    __block NSString * valCookie;

    __block NSString * valToken;

    JSONRPCService * service = /color][color=#578187]JSONRPCService[/color][color=#000000] [/color]serviceWithURL[color=#000000]:serviceURL [/color]version[color=#000000]:[/color]JSONRPCVersion_2_0[color=#000000;


    service [color=#38595d]callMethodWithNameAndParams[/color]:[color=#c72c25]@&quot;login&quot;[/color], [color=#b41ca4]self[/color].[color=#7134aa]log[/color], [color=#b41ca4]self[/color].[color=#7134aa]pwd[/color], [color=#b41ca4]nil[/color completion:^(JSONRPCMethodCall * methodCall,id result,NSError * error)

    {

    NSArray * tab = [/color][color=#7134aa]NSHTTPCookieStorage[/color][color=#000000] [/color]sharedHTTPCookieStorage[color=#000000 cookiesForURL:service.serviceURL];


    int i=[tab count];

    for(int j=0;j<i;j++)

    {

    NSHTTPCookie * Cookie;

    Cookie = [tab objectAtIndex:j];

    if (Cookie [color=#401082]name[/color isEqualToString:@VHTSESSION])

    {

    NSLog(@cookie1: %@",[Cookie value]);

    valCookie=[Cookie value];

    NSLog(@cookie2: %@",valCookie);

    service [color=#38595d]callMethodWithNameAndParams[/color]:[color=#c72c25]@&quot;get_token&quot;[/color], [color=#b41ca4]nil[/color completion:^(JSONRPCMethodCall * methodCall,id result,NSError * error)

    {

    NSLog(@token1: %@",result);

    valToken=result;

    NSLog(@token2: %@",valToken);

    [self userDidLoginWithCookie:valCookie andToken:valToken];

    }

    ];

    }

    }



    }

    ];

    }









    -(void)userDidLoginWithCookie:(NSString*)valCookie1 andToken:(NSString*)valToken1

    {

    NSLog(@%@ et %@",valCookie1,valToken1);

    [self setCook:valCookie1];

    [self setTok:valToken1];

    }





    et pour pouvoir exécuter ma méthode login:







    //


    // ViewController.m


    // vht2


    //


    // Created by Yassine Badih on 11/04/12.


    // Copyright (c) 2012 __MyCompanyName__. All rights reserved.


    //






    #import "ViewController.h"




    #import "Authentification.h"




    @interface ViewController ()




    @end




    @implementation ViewController



    - (void)viewDidLoad

    {

    /color][color=#b41ca4]super[/color][color=#000000] [/color]viewDidLoad[color=#000000;


    Authentification * Auth=[/color]Authentification[color=#000000] [/color][color=#401082]alloc[/color][color=#000000] ][/color][color=#401082]init[/color][color=#000000;


    [Auth login];

    NSLog(@Enfin voici la valeur tu token: %@",[Auth tok]);




    }





    mais du coup à  l'affichage de la réponse:



    2012-04-18 11:25:54.139 vht2[712:f803] Enfin voici la valeur tu token: (null)

    2012-04-18 11:25:54.329 vht2[712:f803] cookie1: d266rufgioag7buvhi9m2itcd2

    2012-04-18 11:25:54.330 vht2[712:f803] cookie2: d266rufgioag7buvhi9m2itcd2

    2012-04-18 11:25:54.368 vht2[712:f803] token1: 651dde707c6d63b5f68d899d17f9cd77

    2012-04-18 11:25:54.391 vht2[712:f803] token2: 651dde707c6d63b5f68d899d17f9cd77

    2012-04-18 11:25:54.392 vht2[712:f803] d266rufgioag7buvhi9m2itcd2 et 651dde707c6d63b5f68d899d17f9cd77





    Je comprend pas du coup, j'ai loupé une étape ? Je croyais pourtant pouvoir dans ma méthode userDidLoginWithCookie avoir bien traité la méthode login, le temps que la requête soit envoyé et que la réponse soit reçus.



    Désolé si je t'ai mal compris Ali, j'essaye de faire de mon mieux image/sad.png' class='bbc_emoticon' alt=':(' />
  • AliGatorAliGator Membre, Modérateur
    Bah non t'as bien compris, quel est le problème ?

    Que ton NSLog t'affiche (null) pour le token ? C'est normal, puisque quand ton NSLog s'exécute, ta méthode login a été exécutée (la requête au WebService a été envoyée) mais n'a pas encore eu le temps de recevoir la réponse (le temps que le serveur réponde, selon la qualité de ton réseau) donc que ta méthode "userDidLoginWithCookie:token:" n'a pas encore été appelée.



    Faut que tout le code que tu veux exécuter seulement une fois que le login est terminé, tu le mettes dans "userDidLoginWithCookie:token:", donc dans la méthode appelée quand le login a reçu sa réponse.
  • yass_1988yass_1988 Membre
    avril 2012 modifié #38
    OK Ali, merci, je comprend mieux du coup.

    Et du coup j'ai une autre question, maintenant que ma méthode est définie, que j'arrive bien à  récupérer mon cookie de session et mon token. Je souhaiterais pouvoir définir une autre méthode, la méthode Logout, pour pouvoir me déconnecter du serveur avec la signature ci-jointe:



    "logout":{"envelope":"JSON-RPC-2.0","transport":"POST","parameters":[],"returns":"boolean"}



    Donc on suivant tes conseil et en m'inspirant de la méthode login j'ai essayé de pondre quelque chose:





    -(void) logout

    {

    NSString * http=@"http://";;

    NSString * suite=@/auth/rpc.php;

    NSString * lien=[NSString stringWithFormat:@%@%@%@",http,self.adre,suite];

    NSURL * serviceURL = [NSURL URLWithString:lien];

    __block BOOL deconect;

    JSONRPCService * service = /color][color=#578187]JSONRPCService[/color][color=#000000] [/color]serviceWithURL[color=#000000]:serviceURL [/color]version[color=#000000]:[/color]JSONRPCVersion_2_0[color=#000000;

    service [color=#38595d]callMethodWithNameAndParams[/color]:[color=#c72c25]@&quot;logout&quot;[/color], [color=#b41ca4]nil[/color completion:^(JSONRPCMethodCall * methodCall,id result, NSError * error)

    {

    deconect=result; //Avertissement 1

    [self userDidLogout:deconect]; //Erreur

    }];

    }



    -(void)userDidLogout:(BOOL)valeur ///Avertissement 2

    {

    if (valeur) {NSLog(@Vous vous êtes bien deconnecter de l'application);}

    else {NSLog(@Vous n'avez parvenu à  vous deconnecter);}

    }







    Du coup pas mal d'avertissement et d'erreur:

    Avertissement 1: Incompatible pointer to integer conversion assigning to 'BOOL' (aka 'signed char') from '__strong id';

    Avertissement 2: Conflicting paramètre types in implémentation of 'userDidLogout:':'__strong id' vs 'BOOL' (aka 'signed char')

    Erreur: Implicit conversion of 'BOOL'(aka 'signed char') to 'id' is disallowed with ARC



    Une idée image/huh.gif' class='bbc_emoticon' alt='???' />
  • AliGatorAliGator Membre, Modérateur
    Quand tu décodes du JSON, cela te renvoie des NSObjects (NSArray, NSDictionary, NSString, ...).

    Un booléen ou un entier sont donc représentés par les librairies JSON (SBJSON que j'utilise ou NSJSONSerialization de iOS5, etc) par des objets (id / NSObject) au même titre que les autres données. Pour cela, ces types de données atomiques sont encapsulé dans un NSNumber. ([NSNumber numberWithBOOL:YES/NO] pour un booléen, [NSNumber numberWithInt:x] ou [NSNumber numberWithFloat:y] etc pour les nombres)



    Donc quand tu récupères le "result" dans le bloc en retour de ton appel JSON-RPC à  logout, c'est un objet de type "id" que tu récupères de toute façon, donc si le WebService te dit que logout retourne un booléen ça va se formaliser par un NSNumber qui porte une boolValue.



    [font=helvetica, arial, sans-serif]
    deconect = [result boolValue]; // pour extraire la représentation BOOL du NSNumber result
    
    [/font]



    PS : Note que toutes les questions que tu poses ne sont pas spécialement liées à  JSON-RPC, mais sont des questions assez génériques à  ObjC et Cocoa...
  • Désolé, j'essayerais la prochaine fois de faire la part dans mes questions.



    Du coup je voudrais revenir sur ton post juste avant:


    Faut que tout le code que tu veux exécuter seulement une fois que le login est terminé, tu le mettes dans "userDidLoginWithCookie:token:", donc dans la méthode appelée quand le login a reçu sa réponse.




    Je vois clairement, sauf que dans mon cas, imaginons cette situation, j'ai défini une classe Authentification, ou j'implémente ma méthode login, en renseignant mon token et mon cookie. et que mnt au lancement de mon appli, dans mon viewController je veuille définir un objet Authentification et j'appelle ma méthode login qui renseignera mon cooki et mon token, tout mon code qui viendra après et qui dépend de login (Style appellé une autre vue si mon login a bien renseigné cookie et token). Ce code là  je serais obligé de le mettre dans ma méthode userDidLoginWithCookie image/huh.gif' class='bbc_emoticon' alt='???' />?



    [font="'lucida sans unicode"]Comme tu le dis faut Faut que tout le code que je veux exécuter seulement une fois que le login est terminé, je le mettes dans "userDidLoginWithCookie:token:", donc dans la méthode appelée quand le login a reçu sa réponse, sauf que là  pour mon exemple (Et d'ailleur j'ai pas le choix) je sais pas si c'est possible.[/font]



    [font="'lucida sans unicode"]Dans tout les cas à  un moment donné va falloir que je dise à  ma vue de changer de vue si mon cookie et mon token est bien renseigné.[/font]



    [font="'lucida sans unicode"]J'en peux plus, toute le journée que je suis dessus !!!!!!!!!!!!!!!!!!![/font]

    [font="'lucida sans unicode"]Help !!!!![/font]

    [font="'lucida sans unicode"] image/crybaby.gif' class='bbc_emoticon' alt=' :'( ' />[/font]
  • C'est bon j'ai réussi à  contourné le problème, mais j'ai du passé par une classe du coup et du utilisé des thread et des NSCondition, assez barbare j'avoue, mais au moin je réussi à  contourné le coté asynchrone sinon je pouvais pas avancé dans l'application.



    Authentification.m:





    - (void) login

    {

    NSString * http=@"http://";;

    NSString * suite=@/auth/rpc.php;


    NSString * lien=[NSString stringWithFormat:@%@%@%@",http,self.adre,suite];

    SynchronousRpc * SyncRPC=[/color]SynchronousRpc[color=#000000] [/color][color=#401082]alloc[/color][color=#000000 init:lien];






    NSArray * loginParamTab=color=#7134aa]NSArray[/color] [color=#401082]arrayWithObjects[/color]:[color=#b41ca4]self[/color].[color=#7134aa]log[/color],[color=#b41ca4]self[/color].[color=#7134aa]pwd[/color],[color=#b41ca4]nil[/color;

    [SyncRPC call:@login parameters:loginParamTab];

    color=#b41ca4]self[/color] [color=#38595d]setCook[/color]:[SyncRPC [color=#38595d]cookie[/color];



    NSArray * tokenParamTab=color=#7134aa]NSArray[/color] [color=#401082]array[/color;

    id resultat=[SyncRPC callWithSession:@get_token parameters:tokenParamTab session:color=#b41ca4]self[/color] [color=#38595d]cook[/color];

    NSString * valToken=resultat;

    [self setTok:valToken];



    }



    SynchronousRpc.m:





    #import "SynchronousRpc.h"




    @implementation SynchronousRpc



    -(id) resultat;

    {

    return resultat;


    }



    -(NSString *) cookie;

    {

    return cookie;

    }



    -(void) setCookie : (NSString *)nouvCookie;

    {

    cookie=nouvCookie;

    }



    -(void) setResultat : (id)nouvResultat;

    {

    resultat=nouvResultat;

    }





    -(void) setAdre : (NSString *)nouvAdre

    {

    adre=nouvAdre;

    }





    - (id) init:(NSString *)nouvAdre

    {

    if ( self = color=#b41ca4]super[/color] [color=#401082]init[/color )

    {

    finished=NO;

    [self setAdre:nouvAdre];

    Cond = [color=#7134aa]NSCondition[/color] [color=#401082]alloc[/color init];

    NSURL * serviceURL = color=#7134aa]NSURL[/color] [color=#401082]URLWithString[/color]:[color=#578187]adre[/color;

    service = /color][color=#578187]JSONRPCService[/color][color=#000000] [/color]serviceWithURL[color=#000000]:serviceURL [/color]version[color=#000000]:[/color]JSONRPCVersion_2_0[color=#000000;


    }

    return self;


    }





    -(void)threadedServiceCall:(NSArray *)params

    {

    NSURL * serviceURL = color=#7134aa]NSURL[/color] [color=#401082]URLWithString[/color]:[color=#578187]adre[/color;



    NSString * methodName = [params objectAtIndex:0];

    NSArray * parameters = [params objectAtIndex:1];

    if ([params count] == 3) {

    //we have a cookie to set


    NSDictionary * dictionnaire = color=#7134aa]NSDictionary[/color] [color=#401082]dictionaryWithObjectsAndKeys[/color]:[params [color=#401082]objectAtIndex[/color]:[color=#3d01d9]2[/color, @value,@VHTSESSION, @name,[serviceURL host] ,@domain, @/ ,@path, nil];

    NSHTTPCookie * theCookie=[color=#7134aa]NSHTTPCookie[/color] [color=#401082]alloc[/colorinitWithProperties:dictionnaire];

    [/color][color=#7134aa]NSHTTPCookieStorage[/color][color=#000000] [/color]sharedHTTPCookieStorage[color=#000000 setCookie:theCookie];


    }



    [[service callMethodWithName:methodName parameters:parameters]

    completion:^(JSONRPCMethodCall * methodCall,id result,NSError * error)

    {

    resultat=result;



    NSArray * tab = [color=#7134aa]NSHTTPCookieStorage[/color] [color=#401082]sharedHTTPCookieStorage[/color cookiesForURL:serviceURL];

    //je récupére la valeur du cookie que je renseignera dans un champs cookie dans ma classe SynchronousRpc


    int i=[tab count];

    NSString * valCookie;

    for(int j=0;j<i;j++)

    {

    NSHTTPCookie * Cookie;

    Cookie = [tab objectAtIndex:j];

    if (Cookie [color=#401082]name[/color isEqualToString:@VHTSESSION])

    {

    valCookie=[Cookie value];

    }

    }

    [self setCookie:valCookie];



    color=#578187]Cond[/color] [color=#401082]lock[/color;

    finished=YES;

    color=#578187]Cond[/color] [color=#401082]signal[/color;

    color=#578187]Cond[/color] [color=#401082]unlock[/color;

    }

    ];



    while (!finished) {

    NSDate * to = [/color][color=#7134aa]NSDate[/color][color=#000000] [/color]alloc[color=#000000 initWithTimeIntervalSinceNow:1];


    [/color][color=#7134aa]NSRunLoop[/color][color=#000000] [/color]currentRunLoop[color=#000000 runMode:NSDefaultRunLoopMode beforeDate:to];


    }

    }





    - (void)call:(NSString *)methodName parameters:(NSArray*)params

    {

    @synchronized(self) {




    finished=NO;

    color=#578187]Cond[/color] [color=#401082]lock[/color;



    NSArray * paramtab = color=#7134aa]NSArray[/color] [color=#401082]arrayWithObjects[/color]:methodName,params, [color=#b41ca4]nil[/color;

    [NSThread detachNewThreadSelector:@selector(threadedServiceCall:) toTarget:self withObject:paramtab];



    NSDate * to = [/color][color=#7134aa]NSDate[/color][color=#000000] [/color]alloc[color=#000000 initWithTimeIntervalSinceNow:1];


    [Cond waitUntilDate:to];



    color=#578187]Cond[/color] [color=#401082]unlock[/color;



    if(color=#b41ca4]self[/color] [color=#38595d]resultat[/color!=nil)

    {

    NSLog(@Il y a une erreur lors de connection);


    }

    }

    }





    - (id)callWithSession:(NSString *)methodName parameters:(NSArray*)params session:(NSString*)session

    {

    @synchronized(self) {




    finished=NO;

    color=#578187]Cond[/color] [color=#401082]lock[/color;



    NSArray * paramtab = color=#7134aa]NSArray[/color] [color=#401082]arrayWithObjects[/color]:methodName,params,session, [color=#b41ca4]nil[/color;

    [NSThread detachNewThreadSelector:@selector(threadedServiceCall:) toTarget:self withObject:paramtab];



    NSDate * to = [/color][color=#7134aa]NSDate[/color][color=#000000] [/color]alloc[color=#000000 initWithTimeIntervalSinceNow:5];


    [Cond waitUntilDate:to];



    color=#578187]Cond[/color] [color=#401082]unlock[/color;



    if(color=#b41ca4]self[/color] [color=#38595d]resultat[/color!=nil)

    {

    return color=#b41ca4]self[/color] [color=#38595d]resultat[/color;

    } else

    {

    NSLog(@Erreur pas de retour résultat);


    return nil;

    }

    }

    }



    @end
  • AliGatorAliGator Membre, Modérateur
    image/crazy.gif' class='bbc_emoticon' alt=' B) ' /> J'ai le droit de vomir ?



    Dans toute application mobile qui interagit avec le réseau à  un moment donné ou à  un autre, de toute façon tu auras le cas de l'asynchronisme, le temps que la requête soit envoyée, la réponse reçue, parce que sur un mobile on est pas en ADSL et qu'on ne capte pas toujours bien.

    Transformer ces opérations, asynchrones par nature, en méthode synchrones, et donc bloquantes, c'est quand même bien crade et le truc à  éviter (même si tu l'as threadé)



    Je ne comprend toujours pas pourquoi tu veux absolument le rendre synchrone. Pourquoi ne pas mettre le reste de ton code dans la méthode didLogin que tu appelles dans le completionBlock, quand la requête a reçu sa réponse ? Ton architecture de code est certainement mal pensée en tout cas pas du tout pensée avec le fait que certaines actions nécessitent un temps de latence et qu'il faut faire patienter l'utilisateur.
  • Je suis obligé de faire du code en dépendant de ma méthode login ne serait ce que pour le token afin d'envoyer d'autre requête, si je suis ton exemple, je serais obligé de foutre toute mon appli dans une seule méthode image/huh.gif' class='bbc_emoticon' alt='???' />



    C'est ingérable, tout mon appli se base sur le faite de pouvoir envoyer des requêtes JSON-RPC.

    Quand j'envois ma méthode login, j'aimerais passé à  autre chose mais je veux quand même que avant d'entreprendre quoi que ce soit que je puisse avoir les information envoyé par la méthode login. Sauf que là  je vois pas comment faire.



    traitement 1 ....

    [Auth login];

    traitement 2 ...



    En fessant ainsi et du fait que login est asynchrone je passe directe au traitement 2 pendant que login continu son traitement a elle. Alors que je veux que traitement 2 utilise les informations envoyé par login. Et je peux t'assurer que c'est 10 milles fois plus à  vomir si je fous tout mon traitement dans la méthode didLogin appellé par login.



    Tu vois ou est le problème ?
  • Je suis actuellement dans le même cas que toi.

    Et j'appelle ma méthode d'authentification en mode asynchrone, pourtant je suis obligé comme toi de récupérer un token.

    Quand j'appelle ma méthode de login, je démarre un petit activity indicator que je stoppe une fois que ma méthode est terminée. Si ma méthode me retourne une réponse positive, je passe au contrôleur suivant.

    Je pense en faite que ton problème viendrait de ta logique d'enchaà®nement de tes méthodes...
  • AliGatorAliGator Membre, Modérateur
    avril 2012 modifié #45
    'yass_1988' a écrit:


    Je suis obligé de faire du code en dépendant de ma méthode login ne serait ce que pour le token afin d'envoyer d'autre requête, si je suis ton exemple, je serais obligé de foutre toute mon appli dans une seule méthode image/huh.gif' class='bbc_emoticon' alt='???' />
    Bah non tout au contraire même !

    Dans ton cas c'est plutôt toi qui met tout dans une seule méthode j'ai l'impression, tu appelles traitement1, puis login, puis traitement2, le tout dans la même méthode, alors que login a besoin d'attendre la réponse du serveur avant de continuer.


    'yass_1988' a écrit:
    C'est ingérable, tout mon appli se base sur le faite de pouvoir envoyer des requêtes JSON-RPC.
    Raison de plus pour gérer ça avec des HUD d'attente le temps que les requêtes soient envoyées, ou un truc dans ce genre, et donc tout en asynchrone.
    'yass_1988' a écrit:
    Quand j'envois ma méthode login, j'aimerais passé à  autre chose mais je veux quand même que avant d'entreprendre quoi que ce soit que je puisse avoir les information envoyé par la méthode login. Sauf que là  je vois pas comment faire.
    Bah il suffit d'afficher un petit spinner d'attente (via des classes comme SVProgressHUD ou similaire par exemple) à  l'écran quand tu envoies ta méthode de login, pour demander à  l'utilisateur d'attendre (de toute façon il devra attendre, en mode synchrone ou asynchrone, que le login ait retourné le token, donc autant le faire patienter avec un ProgressHUD ou un spinner plutôt que de lui donner l'impression que ton appli est plantée). Et quand la méthode de login reçoit la réponse, enlever le progressHUD puisque la requête a reçu sa réponse et son token, et permettre ainsi à  l'utilisateur de continuer à  utiliser l'appli, envoyer d'autres requêtes, etc.


    'yass_1988' a écrit:
    En fessant ainsi et du fait que login est asynchrone je passe directe au traitement 2 pendant que login continu son traitement a elle. Alors que je veux que traitement 2 utilise les informations envoyé par login.
    Bah oui c'est tout le problème, traitement2 utilise les infos de login donc faut bien que tu attendes que login ait fini et que didLogin soit appelé pour appeler traitement2.
    'yass_1988' a écrit:
    Et je peux t'assurer que c'est 10 milles fois plus à  vomir si je fous tout mon traitement dans la méthode didLogin appellé par login.
    Je ne vois pas en quoi. Mettre ton appel à  ta méthode traitement2 dans didLogin ça t'évite de faire un thread, de risquer tous les problèmes de gestion du multithreading et partage de ressources, etc. Sans parler de tous les locks et conditions que tu dois gérer rien que pour ça (et encore dans ton cas tu n'as qu'une seule méthode pour l'instant, login, je te parle même pas de quand tu en auras plusieurs).

    PS : Et ça c'est sans parler des conventions de nommage que tu ne respectes pas (variables avec une minuscule, etc...)


    'yass_1988' a écrit:
    Tu vois ou est le problème ?
    Bah pas trop en fait.



    Ou alors, si tu trouves que c'est un peu crade de mettre le reste du code dans une méthode "didLogin" à  part, et donc au niveau lisibilité de ne plus avoir sous les yeux l'enchaà®nement des méthodes, là  oui je te rejoins. Mais là  dans ce cas, utilise les blocks, ils sont faits pour ça !!!





    Si ton code ressemblait à  ça, ça t'irait mieux ? Car c'est ce que permettrait l'utilisation des blocks plutôt que du pattern delegate (et c'est précisément ce qui est utilisé dans mon framework JSON-RPC d'ailleurs. Je t'ai parlé de prévoir une méthode didLogin au début car je ne voulais pas t'introduire à  la syntaxe des blocks dès le début, vu qu'il faut avouer qu'elle peut être déroutante de prime abord, mais au niveau lisibilité de l'enchaà®nement du code, c'est 100x mieux avec les blocks
    <br />
    [self traitement1]; // faire ceci au début<br />
    // Puis demander le login<br />
    [self loginWithCompletion:^(NSString* cookie, NSString* token) {<br />
      // et exécuter ce code uniquement quand le login a fini et a obtenu la réponse et qu&#39;on a cookie et token<br />
      [self traitement2];<br />
    }];
    
    Pour pouvoir écrire ce code, c'est vraiment pas compliqué : au lieu quand le login a fini d'appeler la méthode didLogin, il suffit de passer un block en paramètre à  ta méthode login (renommée du coup loginWithCompletion pour l'occasion), et d'appeler ce block à  la place de l'appel à  didLogin. C'est beaucoup plus propre et beaucoup plus lisible, et ça t'évite de prendre des risques en créant des threads (qui sont en plus obsolètes de nos jours avec GCD &amp; co, en plus d'être dangereux dans le sens où il faut penser à  beaucoup de choses, deadlocks, protection de ressources, vérification que tous les appels effectués sont thread-safe, etc).
Connectez-vous ou Inscrivez-vous pour répondre.