2 votes

Créer un UISearchDisplay avec des appels réseau asynchrones dans iOS

Une vue de mon application iOS est un UISearchDisplay. Je l'ai conçu comme une recherche en amont, de sorte qu'à chaque fois que l'utilisateur saisit un nouveau caractère, la table se remplit à nouveau. Pour ce faire, j'ai implémenté la méthode du protocole UISearchDisplayDelegate :

searchDisplayController:shouldReloadTableForSearchString:

Dans cette méthode, je prends la chaîne fournie et je l'ajoute à mon URL de requête. Je crée ensuite une nouvelle connexion NSURLConnection et soumets une nouvelle requête asynchrone. Je reçois et ajoute des données via la méthode delegate :

connection:didReceiveData:

Une fois que la connexion a terminé le téléchargement des données, via la méthode :

connectionDidFinishLoading

Je passe les données à une instance de NSXMLParser. Les données reçues sont un fichier XML de tous les contacts de ma base de données qui correspondent à la chaîne donnée. Une fois les données analysées, je recharge la table.

Mon problème : Si l'utilisateur tape un texte assez rapidement, plusieurs tâches de connexion et d'analyse seront exécutées en même temps. C'est un problème parce que j'ai une instance de NSMutableData à laquelle j'ajoute des données et que j'analyse. J'espère que vous voyez où je veux en venir.

Quelqu'un a-t-il des suggestions pour améliorer ma mise en œuvre et/ou résoudre ce problème de section critique ?

0voto

Amy Worrall Points 9975

NSXMLParser n'est pas asynchrone. Ce point fait trébucher beaucoup de gens, car ils supposent que c'est dû à l'utilisation de méthodes de rappel déléguées. Cependant, en réalité, la méthode parse ne revient pas tant que l'analyse n'est pas terminée.

Ainsi, bien que vous puissiez avoir plusieurs connexions simultanées, vous n'aurez pas d'opérations d'analyse multiples, à moins que vous n'ayez vous-même mis en place un système multithread.

Pour résoudre le problème des connexions multiples, pourquoi ne pas avoir une seule NSMutableData par connexion ? Il y a plusieurs façons de procéder : vous pouvez consulter les réponses aux questions suivantes pour trouver des idées.

-1voto

Max Desyatov Points 175

Il existe une implémentation intéressante décrite à l'adresse suivante Recherche asynchrone annulable avec UISearchDisplayController

L'essentiel de la solution est le suivant :

  • Créer un NSOperationQueue où vous effectuerez votre opération de recherche et l'enregistrez dans une propriété de votre fichier UISearchDisplayDelegate nommons-le searchQueue .

  • Mettre en œuvre searchDisplayController:shouldReloadTableForSearchString: méthode. Notez que cette méthode renvoie un BOOL qui signale au UISearchDisplayController pour recharger la vue du tableau. La méthode pourrait être mise en œuvre de la manière suivante :

    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller 
    shouldReloadTableForSearchString:(NSString *)searchString {
        if ([searchString isEqualToString:@""] == NO) {
            [self.searchQueue cancelAllOperations];
            [self.searchQueue addOperationWithBlock:^{
    
              NSArray *results = // fetch the results from
              // somewhere (that can take a while to do)
    
              // Ensure you're assigning to a local variable here.
              // Do not assign to a member variable.  You will get
              // occasional thread race condition related crashes 
              // if you do.            
    
              [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                // Modify your instance variables here on the main
                // UI thread.
                [self.searchResults removeAllObjects]; 
                [self.searchResults addObjectsFromArray:results];
    
                // Reload your search results table data.
                [controller.searchResultsTableView reloadData];
              }];
            }];
    
            return NO;
    
        } else {
            [self.searchResults removeAllObjects];
            return YES;
        }
    }
  • N'oubliez pas d'annuler les opérations en cours lorsque l'utilisateur quitte l'interface de recherche.

         - (void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
             [self.searchQueue cancelAllOperations];
         }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X