35 votes

Objective-C enumerateObjectsUsingBlock vs énumération rapide ?

Quels sont les avantages et les inconvénients des deux approches suivantes :

énumérer en utilisant le bloc

NSArray *myArray = [NSArray new];
[myArray enumerateObjectsUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop) {
    if (anObject == someOtherObject) {
        [anObject doSomething:idx];
        *stop = YES;
    }
}];

énumération rapide

NSArray *myArray = [NSArray new];
int idx = 0
for (id anObject in myArray) {
    if (anObject == someOtherObject) {
        [anObject doSomething:idx];
        break;
    }
    ++idx;
}

0 votes

48voto

Simon Whitaker Points 11881

Cet article de blog couvre les principales différences. En résumé :

  • L'énumération rapide est disponible sur OS X 10.5+, les blocs sont disponibles sur 10.6+.
  • Pour une énumération simple, l'énumération rapide est un peu plus rapide que l'énumération par blocs.
  • Il est plus facile (et plus performant) de faire une énumération simultanée ou inversée avec une énumération par blocs qu'avec une énumération rapide.
  • Lors de l'énumération d'un NSDictionary vous pouvez obtenir la clé et la valeur en une seule fois avec un énumérateur basé sur des blocs, alors qu'avec une énumération rapide, vous devez utiliser la clé pour récupérer la valeur dans un message séparé.

En ce qui concerne le dernier point (énumération NSDictionary), comparez ceci :

for (id key in dictionary)
{
    id obj = [dictionary objectForKey: key];
    // do something with key and obj
}

à ça :

[dictionary enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
    // do something with key and obj
}];

En outre, les deux méthodes protègent les collections mutables contre les mutations à l'intérieur de la boucle d'énumération. Il est intéressant de noter que si vous essayez de modifier la collection à l'intérieur d'une énumération basée sur des blocs, vous obtenez une exception lancée par la méthode de CoreFoundation __NSFastEnumerationMutationHandler ce qui suggère qu'il y a un code commun sous le capot.

 NSMutableArray *myArray = [NSMutableArray arrayWithObjects:@"a", @"b", nil];
 [myArray enumerateObjectsUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop) {
     // Attempt to mutate the array during enumeration
     [myArray addObject:@"c"];
 }];

Sortie :

2011-12-14 22:37:53.716 Untitled[5809:707] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x109614190> was mutated while being enumerated.'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff8cca7286 __exceptionPreprocess + 198
    1   libobjc.A.dylib                     0x00007fff8319ad5e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8cd311dc __NSFastEnumerationMutationHandler + 172
    3   CoreFoundation                      0x00007fff8cc9efb4 __NSArrayEnumerate + 612
    4   Untitled                            0x00000001094efcea main + 250
    5   Untitled                            0x00000001094efbe4 start + 52
    6   ???                                 0x0000000000000001 0x0 + 1
)
terminate called throwing an exceptionRun Command: line 1:  5809 Abort trap: 6           ./"$2"

0 votes

En laissant de côté la performance, quelle version trouvez-vous plus facile à lire au premier coup d'œil ?

1 votes

@rsanchezsaez Question intéressante ! Je trouve qu'un for boucle sur les clés du dictionnaire plus lisible. La syntaxe des blocs n'est toujours pas intuitive pour moi.

0 votes

Pour la valeur de la clé, je trouve block plus intuitif (je viens de C(++) et je n'ai utilisé block qu'une fois)

4voto

Paul.s Points 23073

Les premières pensées qui me viennent à l'esprit

  • Les blocs sont disponibles à partir d'iOS 4. Si vous devez prendre en charge des versions antérieures, vous ne pouvez pas utiliser la syntaxe des blocs.

  • Ils sont assez équivalents en termes de ce qu'ils font, sauf que vous ne pouvez pas accidentellement rater le compteur dans la version bloc.

  • Une autre différence potentielle est que vous pouvez définir le bloc ailleurs et passer dans différents blocs en fonction de votre état.

J'espère que ce n'était qu'un exemple très approximatif car le code est assez pauvre et il existe des moyens plus efficaces de le faire ;)

0 votes

En outre, si je me souviens bien, il a été indiqué dans une vidéo de la WWDC 2010 que l'énumération par blocs est encore plus performante que l'énumération rapide.

1 votes

C'est le problème avec les vidéos, vous savez qu'il y a de bonnes choses dedans, mais bonne chance pour les retrouver plus tard. J'ai regardé les docs pour Enumération : Parcourir les éléments d'une collection et il n'y avait aucune mention particulière d'une augmentation des performances :S

2 votes

En fait, je viens de le trouver. C'est la vidéo "What's New in Foundation for iOS 4" de 2010.

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