2011-11-13 12 views

risposta

62

Guarda le API per NSArray e vedrete il metodo

- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block 

in modo da dare che una una prova

[savedArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 

    //... Do your usual stuff here 

    obj // This is the current object 
    idx // This is the index of the current object 
    stop // Set this to true if you want to stop 

}]; 
+10

da aggiungere - il flag stop è usato chiamando '* stop = YES' (semplicemente' stop = YES' non funziona) – Tim

+2

mi chiedo se questo è più veloce, aggiungendo semplicemente un indice intero –

9

Suppongo che la soluzione più smussato per questo sarebbe per incrementare semplicemente un indice manualmente.

NSUInteger indexInSavedArray = 0; 
for (MyClass *entry in savedArray) { 
    indexInSavedArray++; 
} 

In alternativa, non è possibile utilizzare l'enumerazione rapida.

for (NSUInteger indexInSavedArray = 0; indexInSavedArray < savedArray.count; indexInSavedArray++) { 
     [savedArray objectAtIndex:indexInSavedArray]; 
    } 
+5

Anche lui può usare '[savedArray indexOfObject: l'ingresso];' :) –

+6

Sì, che avrebbe funzionato, anche se sarebbe molto inefficiente in quanto avrebbe dovuto inviare IsEqual ad ogni oggetto che porta alla oggetto corrispondente . Ad esempio, occorrerebbero 500 mandate di messaggi isEqual (e calcoli se l'oggetto effettivamente fa qualcosa in real in isEqual) per ottenere l'indice del 500esimo elemento, e quindi 501 ulteriori messaggi inviati per ottenere l'oggetto successivo dopo quello. modifica: forse eri sarcastico e mi sono perso uno scherzo :) –

7

Questa domanda è già stato risposto, ma ho pensato che aggiungerebbe che il conteggio delle iterazioni è in realtà la tecnica menzionata nella documentazione della libreria per sviluppatori iOS:

NSArray *array = <#Get an array#>; 
NSUInteger index = 0; 

for (id element in array) { 
    NSLog(@"Element at index %u is: %@", index, element); 
    index++; 
} 

Ero sicuro che ci sarebbe stato un trucco stravagante, ma immagino di no. :)

+1

La via di Apple non è sicura e IMHO deve essere evitato - diventa orribilmente sbagliato quando qualcuno aggiunge innocentemente una "pausa" o una "prosecuzione" al codice. Purtroppo, il loro design per Fast Enumeration non era molto buono. – Adam

+0

Vuoi dire che qualcosa va storto se il "break" o "continue" è inserito nel codice di Enumerazione veloce? Apple ha fatto qualcosa di diverso rispetto, diciamo, C#? Sto solo chiedendo la mia istruzione (ed evito i futuri bug). Grazie! – GrandAdmiral

+3

Semplice esempio: il codice di esempio è lungo 2 righe. Cosa succede se è lungo 20 righe e alla riga 5 qualcuno aggiunge un "continua"? Il continuare farà avanzare "l'elemento", ma non l'"indice". Aha! Quindi metti l'indice ++ all'inizio, subito dopo il punto in cui è stato utilizzato. Ma cosa succede se qualcuno poi cerca di farvi riferimento più tardi nel corpo del ciclo? Ora è troppo grande per 1. ... ecc. – Adam

0

Una semplice osservazione: se si inizializza l'indice su -1 e si inserisce l'indice ++ come prima riga nel ciclo for, non copre tutte le basi (a condizione che qualcuno non elimini il codice in fronte dell'incremento)?

+1

"a condizione che qualcuno non elimini il codice di fronte all'incremento" La codifica basata sulla fede al suo meglio – Tim

3

Se si desidera accedere all'indice o tornare al di fuori del blocco qui è un pezzo di codice che può essere utile. (considerando che l'array è un array di NSString).

- (NSInteger) findElemenent:(NSString *)key inArray:(NSArray *)array 
{ 
    __block NSInteger index = -1; 
    [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
     if ([obj isEqualToString:key]) { 
      *stop = YES; 
      index = idx; 
     } 
    }]; 
    return index; 
}