76

Ostatnio często korzystam z usługi enumerateObjectsUsingBlock: w celu szybkiego wyliczenia. Mam trudności ze zrozumieniem korzystania z BOOL *stop w bloku wyliczeniowym.Co to jest argument zatrzymania BOOL * dla enumerateObjectsUsingBlock: używany dla?

W NSArray klasy stany referencyjne

stop: Odwołanie do wartości logicznej. Blok może ustawić wartość na YES na zatrzymać dalsze przetwarzanie tablicy. Argument stop jest argumentem tylko-out. Powinieneś tylko ustawić tę wartość logiczną na YES w bloku .

Więc oczywiście mogę dodać następujących w moim bloku, aby zatrzymać wyliczanie:

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

od tego, co byłem w stanie powiedzieć, które nie są wyraźnie ustalone *stop do YES nie ma jakiekolwiek negatywne skutki uboczne. Wyliczenie wydaje się automatycznie zatrzymywać na końcu tablicy. Czy w bloku jest potrzebne naprawdę *stop?

Odpowiedz

143

Argument stop dla bloku pozwala zatrzymać przedwcześnie wyliczenie . Jest to odpowiednik break z normalnej pętli for. Możesz go zignorować, jeśli chcesz przejść przez każdy obiekt w tablicy.

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]; 
}]; 

Jest to parametr wyjściowy, ponieważ jest to odwołanie do zmiennej z zakresu dzwonisz. Musi być ustawiony wewnątrz twojego bloku, ale przeczytaj wewnątrz enumerateObjectsUsingBlock:, ten sam sposób, w jaki zwykle są przesyłane z powrotem do twojego kodu z wywołań 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

Należy zauważyć, że flaga 'stop' ma charakter doradczy; wyliczanie może być kontynuowane dla pewnej niezdefiniowanej liczby iteracji w przypadku równoczesnym. To znaczy. nie powinieneś ustawiać zmiennej '__block' bezwarunkowo przy każdym przejściu przez wyliczenie i oczekiwać, że będzie to" ostatnia "wartość, gdy użyjesz' stop' do wcześniejszego zakończenia. Powinieneś zawsze łączyć "nie, używaj tego obiektu" z ustawieniem 'stop = YES;'. – bbum

+0

@bbum, czy możesz wyjaśnić, czy ciągłe zachowanie odnosi się wyłącznie do równoległego wyliczenia? Chociaż jest to całkowicie zrozumiałe w tym przypadku, nie jest udokumentowane i byłoby dość zaskakującym bite w dupę dla "seryjnego" wyliczenia. –

+3

prosi teraz o wyjaśnienia, ponieważ dokumentacja nie mówi w żaden sposób i powinna. – bbum

Powiązane problemy