Apa argumen BOOL * stop untuk enumerateObjectsUsingBlock: digunakan untuk?

87

enumerateObjectsUsingBlock:Akhir-akhir ini saya banyak menggunakan untuk kebutuhan pencacahan cepat, dan saya mengalami kesulitan memahami penggunaannya BOOL *stopdi blok pencacahan.

The NSArraynegara referensi kelas

stop: Referensi ke nilai Boolean. Blok dapat mengatur nilai YESuntuk menghentikan pemrosesan lebih lanjut dari larik. The stopargumen argumen out-satunya. Anda hanya boleh menyetel Boolean ini ke YESdalam Blok.

Jadi tentu saja saya bisa menambahkan yang berikut ini di blok saya untuk menghentikan pencacahan:

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

Dari apa yang saya sudah bisa memberitahu, tidak secara eksplisit menetapkan *stopuntuk YEStidak memiliki efek samping negatif. Pencacahan tampaknya secara otomatis berhenti sendiri di akhir larik. Jadi, apakah *stopbenar-benar perlu digunakan dalam satu blok?

Mick MacCallum
sumber

Jawaban:

156

The stopargumen untuk Blok memungkinkan Anda untuk menghentikan pencacahan sebelum waktunya . Ini setara dengan dari loop breaknormal for. Anda bisa mengabaikannya jika Anda ingin menelusuri setiap objek dalam larik.

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

Itu adalah parameter keluar karena ini adalah referensi ke variabel dari lingkup pemanggilan. Ini perlu disetel di dalam Blok Anda, tetapi baca di dalamnya enumerateObjectsUsingBlock:, dengan cara yang sama NSErrorbiasanya diteruskan kembali ke kode Anda dari panggilan kerangka kerja.

- (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;
        }
    }
}
jscs
sumber
21
Perhatikan bahwa file stop bendera tersebut adalah penasehat; pencacahan dapat berlanjut untuk beberapa jumlah iterasi yang tidak ditentukan dalam kasus bersamaan, misalnya. Yaitu Anda tidak boleh menetapkan __blockvariabel tanpa syarat pada setiap melewati pencacahan dan berharap itu menjadi nilai "terakhir" saat menggunakan stopuntuk menghentikan awal. Anda harus selalu memasangkan "tidak, gunakan objek ini" dengan pengaturan stop = YES;.
bbum
@bbum, dapatkah Anda menjelaskan apakah perilaku berkelanjutan hanya berlaku untuk pencacahan bersamaan? Meskipun sangat dapat dimengerti dalam kasus itu, itu tidak didokumentasikan, dan akan menjadi gigitan yang cukup mengejutkan untuk pencacahan "serial".
jscs
4
<rdar: // problem / 15015199> sekarang meminta klarifikasi karena dokumentasinya tidak menyebutkan apa pun dan seharusnya.
bbum