NSArraym 在枚举时发生了变异,sqlite3 while 循环?

Posted

技术标签:

【中文标题】NSArraym 在枚举时发生了变异,sqlite3 while 循环?【英文标题】:NSArraym was mutated while being enumerated, sqlite3 while loop? 【发布时间】:2014-11-11 06:44:32 【问题描述】:

我得到了错误:NSArrayM 在被枚举时发生了变异,我已经尝试了几乎所有我可以在 *** 上找到的东西。请记住,我在创建游戏的同时也在学习 :)

我正在使用 sprite kit 并在 didmovetoview 中使用 dispatch_async 来加载游戏。

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)
       // loading stuff, but also this that is causing the error:
       [self buildmap];
    dispatch_async(dispatch_get_main_queue(), ^(void)
        // done loading
    );
);

这是导致崩溃的构建图。

-(void)buildMap 

    int intX = 0;
    int intY = 0;

    sqlite3_stmt *statement;
    if (sqlite3_open([_databasePath UTF8String], &BlockMinerDB) == SQLITE_OK) 

        NSString *sql = [NSString stringWithFormat:@"SELECT blocktype, ladder, blockreachable, walkable, zpos, texture, id, bitmask FROM map ORDER BY id DESC"];
        const char *qstmt = [sql UTF8String];

        if (sqlite3_prepare_v2(BlockMinerDB, qstmt, -1, &statement, NULL) == SQLITE_OK) 

            while (sqlite3_step(statement) == SQLITE_ROW) 

                int blockType = sqlite3_column_int(statement, 0);
                int ladder = sqlite3_column_int(statement, 1);
                int blockReachable = sqlite3_column_int(statement, 2);
                int walkable = sqlite3_column_int(statement, 3);
                int zPos = sqlite3_column_int(statement, 4);
                NSString *texture = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 5)];
                int idBlock = sqlite3_column_int(statement, 6);
                uint32_t newBitmask = (uint32_t)[NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 7)];



                Blocks *testblock = [[Blocks alloc] initWithBlock:blockType blockId:idBlock ladder:ladder scene:self bitmask:newBitmask blockReachable:blockReachable walkable:walkable zPos:zPos texture:texture x:intX y:intY];

                NSLog(@"%@: %i", testblock.name, blockType);

                if ((blockType == 2) || (blockType == 3) || (blockType == 4) || (blockType == 5)) 
                    [blockArrayWalk addObject:testblock];
                 else 
                    [blockArray addObject:testblock];
                


                [background addChild:testblock];
                intX++;
                if (intX == 25) 
                    intX = 0;
                    intY++;
                
            
        
    
    sqlite3_close(BlockMinerDB);

[self buildmap] 使用 sqlite 从数据库中检索地图,我正在使用 while 循环进行循环,这导致了崩溃。它在崩溃之前循环了大约 20-25 次(共 600 次)。

在循环中,我正在创建一个新块(SKSpriteNode 子类),它将块放置在某个位置并带有一些信息(位置、名称、物理等,没有重的东西)。我使用 NSMutableArray 来存储块以便于访问,并认为这是一开始的问题,但是当我删除 [blockArray addObject:block];应用仍然崩溃。

如果我删除 -(void)buildmap 中的所有代码,应用程序不会崩溃。

dispatch_async 和 while 循环是否存在可能导致这种情况的问题?

我现在无法访问代码,但如果有人需要查看更多代码,我可以在大约 8 小时后添加此代码;)非常感谢一些帮助,尝试在 3 周内断断续续地解决此错误现在:D

【问题讨论】:

Objective-C NSMutableArray mutated while being enumerated?的可能重复 我已经删除了对 nsmutablearray 的任何引用,它仍然会产生这个错误。我不会从导致此错误的 buildmap 中的 nsmutablearray 添加/删除对象。 将代码贴在出错位置附近,并突出显示出错的行 用 buildup 更新了我的问题,那个让应用程序崩溃的问题 :) 所以错误出现在 buildMap 中,但具体在哪一行?使用(崩溃线程的)调用堆栈找出答案。 【参考方案1】:

Sprite Kit 可能在任何时间点对子节点进行枚举(可能是为了绘制它们),如果您的调度块随后添加了一个新的子节点,则会导致子数组在枚举时发生变化。

您可以在调度块中填充一个待添加节点的数组,然后在调度块之后一次性添加它们。

【讨论】:

谢谢 :) 现在我可以继续我的游戏了!

以上是关于NSArraym 在枚举时发生了变异,sqlite3 while 循环?的主要内容,如果未能解决你的问题,请参考以下文章

集合 <__NSArrayM: 0x7fa1f2711910> 在枚举时发生了突变

核心数据并发 - 集合在被枚举时发生了变异

集合 <__NSCFString:> 在被枚举崩溃时发生了变异

崩溃 - “集合 <CALayerArray: 0x645dfc0> 在枚举时发生了变异。”

获取 NSGenericException 的原因:'*** Collection <NSConcreteHashTable: 0x282c34140> 在枚举时发生了变异。'

处理后台线程时出现“集合发生变异...”的异常情况