2013-06-28 60 views
1

一些上下文:在我爲Cocos2D破壞的地形庫中,其中一個特徵是可摺疊的地形。爲了有效地摺疊,我將其像素已被更改的列存儲在包含包含整數的NSNumber的NSMutableSet中。我使用這種數據結構,因爲我不想迭代重複的列。正確和最有效的方式來遍歷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 

但是,這導致了不好的結果。該程序將崩潰與一個錯誤訪問內存錯誤。如果我改變for循環使用[alteredColumns allObjects],那麼一切正常。所以問題...可以''in'循環不能用於無序的集合,如NSMutableSet?如果我必須使用諸如allObjects之類的方法,這是否有效?

在此先感謝!

回答

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 

而且這條線你列舉alteredColumns,這符合// 1修改。

+0

你確實是對的。有時很容易忽視小事情。謝謝! –

0
- (void)enumerateObjectsUsingBlock:(void (^)(id obj, BOOL *stop))block 
相關問題