enumerateObjectsUsingBlockのBOOL * stop引数とは何ですか?


87

enumerateObjectsUsingBlock:最近、高速列挙のニーズのために多くを使用していますが、BOOL *stop列挙ブロックでのの使用法を理解するのに苦労しています。

NSArrayクラス参照状態

stop:ブール値への参照。ブロックは値をYESに設定して、配列の以降の処理を停止できます。stop引数はアウト唯一の引数です。このブール値YESはブロック内にのみ設定する必要があります。

したがって、もちろん、ブロックに次のコードを追加して、列挙を停止できます。

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

私が言うことができました何より、明示的に設定していない*stopためにYES任意の負の副作用はありません。列挙は、配列の最後で自動的に停止するようです。では*stop、ブロックで本当に使用する必要がありますか?

回答:


156

stopブロックへの引数により、列挙を途中で停止できます。これbreakは、通常のforループと同じです。配列内のすべてのオブジェクトを調べたい場合は、無視できます。

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

これは、呼び出しスコープからの変数への参照であるため、出力パラメーターです。ブロック内で設定する必要がありますが、内で読み取るとenumerateObjectsUsingBlock:NSErrorフレームワークコールからにコードが返されるのと同じ方法です。

- (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
このstopフラグは参考用です。たとえば、並行処理の場合、列挙はいくつかの未定義の反復で継続する場合があります。__blockつまり、列挙を通過するたびに無条件に変数を設定して、stop早期終了に使用するときに「最後の」値になると期待してはいけません。「いいえ、このオブジェクトを使用する」は常にと組み合わせる必要がありますstop = YES;
bbum

@bbum、継続的な動作が同時列挙にのみ適用されるかどうかを明確にできますか?その場合は完全に理解できますが、文書化されていないため、「シリアル」列挙のロバでの意外な一口になります。
jscs 2013

4
<rdar:// problem / 15015199>は、ドキュメントがどちらの方法も述べていないため、説明を求めます。
bbum 2013
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.