Qual è l'argomento BOOL * stop per enumerateObjectsUsingBlock: usato per?


87

enumerateObjectsUsingBlock:Ultimamente ho usato molto per le mie esigenze di enumerazione rapida e ho difficoltà a capire l'uso di BOOL *stopnel blocco di enumerazione.

Gli NSArraystati di riferimento della classe

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

Quindi, ovviamente, posso aggiungere quanto segue nel mio blocco per interrompere l'enumerazione:

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

Da quello che ho potuto dire, non impostare esplicitamente *stopsu YESnon ha effetti collaterali negativi. L'enumerazione sembra arrestarsi automaticamente alla fine della matrice. Quindi l'uso è *stopdavvero necessario in un blocco?

Risposte:


156

L' stopargomento del blocco consente di interrompere prematuramente l'enumerazione . È l'equivalente di breakun forciclo normale . Puoi ignorarlo se vuoi passare attraverso tutti gli oggetti 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 out perché è un riferimento a una variabile dall'ambito chiamante. Deve essere impostato all'interno del blocco, ma viene letto all'interno enumerateObjectsUsingBlock:, nello stesso modo in cui NSErrori messaggi di posta elettronica vengono comunemente restituiti 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;
        }
    }
}

21
Notare che la stopbandiera è di avviso; l'enumerazione può continuare per un numero indefinito di iterazioni nel caso simultaneo, ad esempio. Cioè non dovresti impostare una __blockvariabile incondizionatamente su ogni passaggio attraverso l'enumerazione e aspettarti che sia l '"ultimo" valore quando si usa stopper terminare anticipatamente. Dovresti sempre accoppiare "no, usa questo oggetto" con l'impostazione stop = YES;.
bbum

@bbum, puoi chiarire se il comportamento continuo si applica solo all'enumerazione simultanea? Sebbene sia perfettamente comprensibile in questo caso, non è documentato e sarebbe un morso abbastanza sorprendente per l'enumerazione "seriale".
jscs

4
<rdar: // problem / 15015199> ora chiede chiarimenti poiché la documentazione non dice nessuno dei due modi e dovrebbe.
bbum
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.