1

一些背景:在我的 Cocos2D 可破坏地形库中,其中一个功能是可折叠地形。为了有效地折叠,我将像素已更改的列存储在 NSMutableSet 中,该 NSMutableSet 包含包含整数的 NSNumber。我正在使用这个数据结构,因为我不想遍历重复的列。

我对如何遍历 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 循环更改为使用 [alteredColumns allObjects],那么一切正常。所以问题...不能在无序集合(如 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([NSSet allObjects]返回一个 NSArray),并枚举该数组。当您alteredColumns在//1 行进行修改时,枚举数组不会发生变异。

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

在这一行中,您正在枚举已在 //1 行中修改的更改列。

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