Dispatch Async

Bonjour,


 


J'aimerai comprendre le fonctionnement d'une chose sur iOS.


J'ai développé une application iOS et je voudrais savoir si j'ai développé de la bonne manière et utiliser les bons outils.


En fait, mon application communique avec mon serveur par un webservice SOAP  (oui c'est vieux jeux.. lol)


Lorsque je suis sur une page et que je fais un appel au webservice de mon serveur, j'aimerai pouvoir changer de page sans qu'il est finit de charger les informations mais l'application reste bloqué sur la page tant que je n'ai pas eu de retour.


 


J'ai essayé d'utiliser les fonctions dispatch_async et dispatch_sync mais je ne comprends pas très bien le fonctionnement.


Enfin je pense avoir compris un peu mais bon voila ce que j'ai compris :


 


dispatch_async(...{


 


  // je fais mon traitement asynchrone


 


  dispatch_sync(...{


       


       //Je met ici le bout de code à  exécuter pour modifier l'ui principale.


 


   });


});


 


Mais j'ai un problème car mes appels au webservices sont encapsulés dans des fonctions.


Quand j'appelle ces fonctions dans la partie async, le performselector n'est jamais appelé.


Quand j'appelle ces fonctions dans la partie sync, ca fonctionne mais ca bloque l'ecran tant que ca n'a pas fini de chargé.


 


Une solution?


 


 


Réponses

  • J'aurais tendance à  peut-être changer la manière dont tu fais tes appels et à  utiliser des blocks.


     


    Si tu évitais de base de faire des appels synchrones...


  • OK.


     


    Peux-tu m'expliquer brièvement comment fonctionne les blocks ?

  • Sinon j'ai vu que je pouvais modifier la fonction NSURLCONnection qui fait l'appel au webservice pour qu'il soit asynchrone ?


    Mais je suis obligé de mettre la fonction encapsulé dans dispatch_sync sinon mon selector n'est pas appelé meme si j'ai changé dans le code du webservice :


     




                [self.handler performSelector:self.action withObject:output];


    par 


                [self.handler performSelectorOnMainThread:self.action withObject:output waitUntilDone:FALSE];


  • LarmeLarme Membre
    juillet 2017 modifié #5

    Peux-tu mettre le code que tu fais durant un appel ? Pas forcément tout le code, mais les grandes lignes, avec le NSURLConnection, l'appel du handler, etc. Pas besoin forcément de tout le parsing de ta réponse.


    NSURLConnection est dépréciée, favorise donc NSURLSession.


  • alors mon ancienne version :


     




    conn = [[NSURLConnection alloc] initWithRequest: request delegate: self];


    En fait j'ai un delegate sur NSURLCONNECTION avec toute les fonctions associés.


     


    la nouvelle version avec NSUrlconnection qui marche mieux:


     


    NSOperationQueue *queue = [[NSOperationQueue alloc] init];


            [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)


            {


                if (error)


                {


                    NSLog(@Error,%@", [error localizedDescription]);


                    [self handleError:error];


                }


                else


                {


                  NSLog(@%@", [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]);


                   /*self.receivedData = [[NSMutableData data] retain];


                   // self.receivedData =  [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];


                    


                */


                    NSString* response = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];


                    [response release];


                    


                    CXMLDocument* doc = [[CXMLDocument alloc] initWithData: data options: 0 error: &error];


                    if(doc == nil) {


                        [self handleError:error];


                        return;


                    }


                    


                    id output = nil;


                    SoapFault* fault = [SoapFault faultWithXMLDocument: doc];


                    


                    if([fault hasFault]) {


                        if(self.action == nil) {


                            [self handleFault: fault];


                        } else {


                            if(self.handler != nil && [self.handler respondsToSelector: self.action]) {


                                [self.handler performSelector: self.action withObject: fault];


                            } else {


                                NSLog(@SOAP Fault: %@", fault);


                            }


                        }


                    } else {


                        CXMLNode* element = [[Soap getNode: [doc rootElement] withName: @Body] childAtIndex:0];


                        if(deserializeTo == nil) {


                            output = [Soap deserialize:element];


                        } else {


                            if([deserializeTo respondsToSelector: @selector(initWithNode:)]) {


                                element = [element childAtIndex:0];


                                output = [deserializeTo initWithNode: element];


                            } else {


                                NSString* value = [[[element childAtIndex:0] childAtIndex:0] stringValue];


                                output = [Soap convert: value toType: deserializeTo];


                            }


                        }


                        


                        if(self.action == nil) { self.action = @selector(onload:); }


                        if(self.handler != nil && [self.handler respondsToSelector: self.action]) {


                            [self.handler performSelectorOnMainThread:self.action withObject:output waitUntilDone:FALSE];


                        } else if(self.defaultHandler != nil && [self.defaultHandler respondsToSelector:@selector(onload:)]) {


                            [self.defaultHandler onload:output];


                        }


                    }


                    


                    [self.handler release];


                    [doc release];


                    [conn release];


                    conn = nil;


                    [self.receivedData release];


                    


                }




            }];


     


    Comme tu peux le voir j'ai mis performSelectorOnMainThread mais si j'appel la fonction qui appelle ce morceau de code en dispatch_async ca n'appelle pas le selector du mainThread.


     


    Ah si je viens de reverifier avec la nouveau code que je t'ai mis et ca fonctionne ca appelle bien le selector du mainthread.


     


     


    Par contre j'ai un autre problème...


    en fait quand je met l'app en background et que je reviens sur l'app ca appelle la fonction dans appDelegate


    enterForeground ...


    Dans cette fonction j'appelle le webservice pour vérifier qu'il n'y a pas de mis à  jour a faire.


    j'appelle donc la fonction dans un dispatch_sync par exemple et en fait j'ai l'impression enfin j'ai pas que l'impression mais ca appelle toute les fonctions que j'ai appelé précédemment.


    Je m'explique si j'ouvre l'app et que je vais dans une certaine page ca appelle une fonction webservice différente puis je reviens à  l'accueil je sors de l'app et je reviens dessus. Mon code qui appelle la mise à  jour est exécuté mais ca appelle aussi la fonction de la page que j'ai ouvert précédemment comme si une fois que tu appelle la fonction avec dispatc_XXX ben ca met dans la pile et c'est toujours exécuté.

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