迭代NSMutableSet的正确和最有效的方法?

时间:2013-06-28 03:09:53

标签: objective-c data-structures cocos2d-iphone

某些上下文:在我的可破坏的Cocos2D地形库中,其中一个功能是可折叠的地形。为了有效地折叠,我将像素已被更改的列存储在NSMutableSet中,该NSMutableSet包含包含整数的NSNumbers。我正在使用这种数据结构,因为我不想迭代重复的列。

我对如何遍历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错误而崩溃。如果我改变for循环使用[changedColumns allObjects],那么一切正常。所以问题......'for in'循环不能用于无序集合,例如NSMutableSet吗?如果我必须使用像allObjects这样的方法,这有效吗?

提前致谢!

2 个答案:

答案 0 :(得分:3)

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

在此行中,您修改alteredColumns。枚举时修改集合是一件坏事,坏事。如果你很幸运,你会得到BAD_ACCESS,最糟糕的是你甚至不会注意到出现问题,直到你完全出乎意料的行为。

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

在这里创建一个NSArray([NSSet allObjects]返回一个NSArray),并枚举这个数组。在第1行修改alteredColumns时,枚举数组不会发生变异。

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

使用此行,您将枚举changedColumns, 在行// 1中进行了修改。

答案 1 :(得分:1)

- (void)enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop))block