1

コンテキスト: Cocos2D の破壊可能な地形ライブラリの機能の 1 つは、折りたたみ可能な地形です。効率的に折りたたむために、ピクセルが変更された列を、整数を含む NSNumbers を含む NSMutableSet に格納します。重複する列を反復処理したくないため、このデータ構造を使用しています。

NSMutableSet をループする方法についての私の最初の本能は、'for in' ループを使用することでした。

for (NSNumber * col in [alteredColumns allObjects]) { // Works 
// for (NSNumber * col in alteredColumns) { // Crashes
    int x = col.intValue;
    bool shouldShift = false;
    bool alphaFound = false;
    for (int y = (size_.height -1); y >= 0; y--) {
        if (!shouldShift) {
            if ([self pixelAt:ccp(x,y)].a == 0) {
                // Need to shift all pixels above one down
                alphaFound = true;
            } else if (alphaFound) {
                didCollapse = shouldShift = true;
                // Ensure the top pixel is alpha'ed out if a collapse will occur
                [self setPixelAt:ccp(x,0) rgba:ccc4(0, 0, 0, 0)];
                [self setPixelAt:ccp(x,(y+1)) rgba:[self pixelAt:ccp(x,y)]];
            } // end inner if
        } else {
            // Need to shift pixels down one
            [self setPixelAt:ccp(x,(y+1)) rgba:[self pixelAt:ccp(x,y)]];
        } // end if
    } // end inner for
    // Remove column from cache if no pixels collapsed
    if (!shouldShift) [alteredColumns removeObject:col];
} // end outer for

しかし、これは悪い結果につながりました。プログラムは、Bad Access Memory エラーでクラッシュします。[alteredColumns allObjects] を使用するように for ループを変更すると、すべて正常に動作します。質問です... NSMutableSet などの順序付けられていないコレクションで「for in」ループを使用できませんか? allObjects などのメソッドを使用する必要がある場合、これは効率的ですか?

前もって感謝します!

4

2 に答える 2

3
if (!shouldShift) [alteredColumns removeObject:col]; //1

この行で変更しalteredColumnsます。列挙中にコレクションを変更することは、悪いことです。運が良ければ、BAD_ACCESS を取得できます。最悪の場合、まったく予期しない動作が発生するまで、何かがうまくいかなかったことにさえ気付かないでしょう。

for (NSNumber * col in [alteredColumns allObjects]) //2

ここで NSArray を作成し ( は NSArray を[NSSet allObjects]返します)、この配列を列挙します。//1 行で変更するalteredColumnsと、列挙型配列は変更されません。

for (NSNumber * col in alteredColumns) { //3

そして、この行で、 //1 行で変更された modifiedColumns列挙しています。

于 2013-06-28T05:42:23.880 に答える
1
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop))block
于 2013-06-28T04:31:10.250 に答える