76

Ultimamente ho utilizzato enumerateObjectsUsingBlock: per le mie esigenze di enumerazione rapida e sto riscontrando difficoltà nell'utilizzo di BOOL *stop nel blocco di enumerazione.Qual è l'argomento stop BOOL * per enumerateObjectsUsingBlock: usato per?

Gli stati di riferimento NSArray classe

stop: Un riferimento a un valore booleano. Il blocco può impostare il valore su YES su interrompere l'ulteriore elaborazione dell'array. L'argomento stop è un argomento solo-out . Dovresti sempre impostare questo booleano su YES all'interno del blocco .

Così poi, naturalmente, posso aggiungere il seguente nel mio blocco per fermare l'enumerazione:

if (idx == [myArray indexOfObject:[myArray lastObject]]) { 
    *stop = YES; 
} 

Da quello che ho potuto dire, non impostando esplicitamente *stop-YES non ha eventuali effetti collaterali negativi. L'enumerazione sembra fermarsi automaticamente alla fine dell'array. Quindi è davvero necessario usare *stop in un blocco?

risposta

143

L'argomento stop per il blocco consente di interrompere l'enumerazione in anticipo. È l'equivalente di break da un normale ciclo for. Puoi ignorarlo se vuoi passare attraverso ogni oggetto dell'array.

for(id obj in arr){ 
    if([obj isContagious]){ 
     break; // Stop enumerating 
    } 

    if(![obj isKindOfClass:[Perefrigia class]]){ 
     continue; // Skip this object 
    } 

    [obj immanetizeTheEschaton]; 
} 

[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
    if([obj isContagious]){ 
     *stop = YES; // Stop enumerating 
     return; 
    } 

    if(![obj isKindOfClass:[Perefrigia class]]){ 
     return; // Skip this object 
    } 

    [obj immanentizeTheEschaton]; 
}]; 

Questo è un parametro fuori perché è un riferimento ad una variabile dall'ambito chiamante. Deve essere impostato all'interno del blocco, ma leggere all'interno di enumerateObjectsUsingBlock:, allo stesso modo NSError s vengono comunemente passati al codice dalle chiamate del framework.

- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block { 
    // N.B: This is probably not how this method is actually implemented! 
    // It is just to demonstrate how the out parameter operates! 

    NSUInteger idx = 0; 
    for(id obj in self){ 

     BOOL stop = NO; 

     block(obj, idx++, &stop); 

     if(stop){ 
      break; 
     } 
    } 
} 
+20

Si noti che il flag 'stop' è di tipo consultivo; l'enumerazione può continuare per un numero indefinito di iterazioni nel caso concorrente, per esempio. Cioè non dovresti impostare una variabile '__block' incondizionatamente su ogni passaggio attraverso l'enumerazione e aspettarti che sia il valore" last "quando usi' stop' per terminare anticipatamente. Dovresti sempre accoppiare il "no, usa questo oggetto" con l'impostazione 'stop = SÌ;'. – bbum

+0

@bbum, puoi chiarire se il comportamento continuato si applica _solo_ all'enumerazione simultanea? Anche se in questo caso è perfettamente comprensibile, non è documentato, e sarebbe un boccone abbastanza sorprendente per l'enumerazione "seriale". –

+3

ora richiede un chiarimento in quanto la documentazione non dice in alcun modo e dovrebbe. – bbum

Problemi correlati