2009-02-16 7 views
5

j'ai un bloc de code qui est similaire à ce qui suit:Enumeration Objective-C 2.0 et rapide lancer des exceptions

for (NSDictionary *tmp in aCollection) { 
    if ([[bar valueForKey:@"id"] isEqualToString:[tmp valueForKey:@"id"]]) 
    { 
     break; 
    } 
    else 
    { 
     [aCollection addObject:bar]; 
     } 
} 

Est-ce techniquement une exception en Objective-C 2.0? Il semble que vous ne pouvez pas muter une collection avec une énumération rapide. Ceci est le résultat d'une erreur:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <NSCFArray: 0x396000> was mutated while being enumerated.' 

Quelle est la meilleure façon de résoudre ce problème?

Répondre

3

De The Objective-C 2.0 Programming Language, vous ne pouvez pas modifier la collection recensée:

Enumeration is “safe”—the enumerator has a mutation guard so that if you attempt to modify the collection during enumeration, an exception is raised.

6

Faites une copie de la collection et itérer cela. Ensuite, vous pouvez échanger ou ajouter à votre collection originale sans problèmes.

12

Eh bien la façon de le résoudre est de ne pas muter le tableau (par exemple, ajouter un objet) tout en énumérant it :)

Le problème ici est que la modification du tableau par des éléments en ajoutant/suppression pourrait provoquer des valeurs de l'énumération à devenir invalide, donc pourquoi c'est un problème.

Dans votre cas La solution la plus simple consiste à corriger le bug dans votre code. Votre code fait la clause "else add" pour chaque élément du tableau et je suis sûr que ce n'est pas ce que vous voulez.

Essayez ceci;

bool found = false; 
for (NSDictionary *tmp in aCollection) 
{ 
    if ([[bar valueForKey:@"id"] isEqualToString:[tmp valueForKey:@"id"]]) 
    { 
     found = true; 
     break; 
    } 
} 

if (!found) 
{ 
[aCollection addObject:bar]; 
} 
6

La ligne

[aCollection addObject:bar] 

est votre problème. Vous ne pouvez pas modifier aCollection en l'énumérant. La meilleure approche serait de créer un NSMutableArray temporaire, ajouter bar à cela, puis appelez [aCollection addObjectsFromArray:] avec votre tableau temporaire.

Par exemple:

NSMutableArray *foundObjects = [NSMutableArray array]; 
for (NSDictionary *aDictionary in aCollection) { 
    if ([[bar objectForKey:@"id"] isEqual:[aDictionary objectForKey:@"id"]]) 
     break; 

    [foundObjects addObject:bar]; 
} 
[aCollection addObjectsFromArray:foundObjects]; 
+7

Pourquoi la peine de faire tout cela quand vous pouvez juste itérer sur '[aCollection copy]'? –

2

copie le tableau. Sinon, vous êtes de jouer avec la collection que nous parcourons:

for (NSDictionary *tmp in aCollection.copy) { 
    if ([[bar valueForKey:@"id"] isEqualToString:[tmp valueForKey:@"id"]]) 
    break; 
    [aCollection addObject:bar]; 
} 
+0

Downvotes? Pourquoi? –

1

Tout le monde a offert des réponses utiles, qui semblent tous corrects.

Votre code, cependant, ne fait pas ce qu'ils pensent qu'il fait. Il ne fait probablement pas ce que vous pensez qu'il fait non plus.

Vous essayez d'ajouter 'bar' à la collection si le premier objet renvoyé par l'énumérateur ne correspond pas à la barre.

Tout le monde pense que vous essayez d'ajouter une barre si elle n'existe pas dans la collection.

Je suppose que vous avez pris une construction Python et que vous l'avez porté incorrectement.

+0

Ceci est un commentaire pas une question. Vous avez probablement raison, cependant :) –

0

résolu

i a le même problème dans les objets CoreData énumération.

ne changent pas sous-objet qui repose dans MATRICE sur lequel la boucle est en marche

Comme, si je changeais/Modifier objet tout sur la boucle .. il donnera cette erreur

for (LoadList *objLL in ArrLoadList) {    // here Enumaration is Going on 
     // here i has removed objects in ArrLoadList and reassign the ArrLoadList .. 
     // it will gives me this error 
     // So Don't change the Main Array object 
}