2009-08-21 5 views
6

Je travaille sur l'implémentation d'un searchBar personnalisé pour une table assez complexe et j'ai de nouveau rencontré ce motif de code. Ceci est un exemple du début livre iPhone développement:Comment Fast Enumeration (looping) fonctionne-t-il en Objective-C? (ie: pour (NSString * aString dans unDictionnaire) ...)

- (void)handleSearchForTerm:(NSString *)searchTerm 
{ 
NSMutableArray *sectionsToRemove = [[NSMutableArray alloc] init]; 
[self resetSearch]; 

for (NSString *key in self.keys) 
    { 
    NSMutableArray *array = [self.names valueForKey:key]; 
    NSMutableArray *toRemove = [[NSMutableArray alloc] init]; 
    for (NSString *name in array) 
    { 
     if ([name rangeOfString:searchTerm 
         options:NSCaseInsensitiveSearch].location == NSNotFound) 
      [toRemove addObject:name]; 
    } 

    if ([array count] == [toRemove count]) 
     [sectionsToRemove addObject:key]; 
    [array removeObjectsInArray:toRemove]; 
    [toRemove release]; 
    } 
[self.keys removeObjectsInArray:sectionsToRemove]; 
[sectionsToRemove release]; 
[table reloadData]; 
} 

La partie que je suis curieux de savoir est le « (nom NSString * dans le tableau) » section. Qu'est-ce que ça fait exactement? Il semble créer une chaîne pour chaque élément du tableau. Aussi, comment cela fonctionne avec les dictionnaires?

Merci!

+0

Merci pour les réponses rapides tout le monde! J'ai édité le titre pour inclure "énumération rapide". – Jonah

Répondre

15

Cette construction est un type différent de boucle for qui s'exécute sur des éléments d'une collection Objective-C, plutôt que sur un tableau C. La première partie définit un objet qui est défini sur un élément de la collection à chaque exécution de la boucle, tandis que la seconde partie est la collection à énumérer. Par exemple, le code:

NSArray *array = [NSArray arrayWithObjects:@"foo", @"bar", nil]; 
for(NSString *string in array) { 
    NSLog(string); 
}

imprimerait:

foo 
bar

Il est la définition d'un NSString *string que, chaque exécution de la boucle, se prépare à l'objet suivant dans le NSArray *array. De même, vous pouvez utiliser l'énumération avec des instances de NSSet (où l'ordre des objets n'est pas défini) et NSDictionary (où il énumérera les clés stockées dans le dictionnaire). Vous pouvez énumérer les valeurs en énumérant les clés, puis en appelant valueForKey: sur le dictionnaire en utilisant cette clé).

Il est très similaire à la construction dans C:

int array[2] = { 0, 1 }; 
for(int i = 0; i < 2; i++) { 
    printf("%d\n", array[i]); 
}

qui imprime:

0 
1

Il est juste une façon syntactique de rendre le code plus lisible et cachant une partie de l'énumération de fantaisie qui va dans la liste des objets dans un NSArray, NSSet ou NSDictionary. Plus de détails sont donnés dans la section Fast Enumeration du document Langage de programmation Objective-C 2.0.

2

C'est une boucle for avec une itération pour chaque clé dans le dictionnaire.

La construction for..in est appelée dénombrement rapide. Vous pouvez en lire plus à ce sujet dans Objective-C 2.0 Programming Guide.

Comment cela fonctionne avec un objet dépend de son implémentation du protocole NSFastEnumeration. Le NSDictionary class reference décrit comment cela fonctionne avec les dictionnaires:

Sous Mac OS X v10.5 et plus tard, NSDictionary prend en charge le protocole NSFastEnumeration. Vous pouvez utiliser la construction for ... in pour énumérer les clés d'un dictionnaire, comme illustré dans l'exemple suivant.

3

Ceci est appelé rapide énumération. Il parcourt le tableau en définissant key sur chaque élément.C'est pareil, fonctionnellement, en faisant ceci:

NSString *key; 
for (NSInteger i = 0; i < [[ self keys ] count ]; i++) { 
    key = [[ self keys ] objectAtIndex:i ]; 

    NSMutableArray *array = [self.names valueForKey:key]; 
    NSMutableArray *toRemove = [[NSMutableArray alloc] init]; 
    for (NSString *name in array) 
    { 
      if ([name rangeOfString:searchTerm 
        options:NSCaseInsensitiveSearch].location == NSNotFound) 
        [toRemove addObject:name]; 
    } 

    if ([array count] == [toRemove count]) 
      [sectionsToRemove addObject:key]; 
    [array removeObjectsInArray:toRemove]; 
    [toRemove release]; 
}