NSGenericException reason Collection <nsconcretemaptable:xxx =“”> </nsconcretemaptable:>

时间:2014-03-18 13:32:15

标签: ios objective-c sprite-kit

这是我看到的错误SKScene,此错误发生随机并且无法复制

*由于未捕获的异常'NSGenericException'而终止应用程序,原因:'* 集合&lt; NSConcreteMapTable:0x1459da60&gt;在被列举时被突变。'

发生了什么?

告诉我你是否需要任何其他信息

感谢

修改

*** First throw call stack:
(
    0   CoreFoundation                      0x025601e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x022298e5 objc_exception_throw + 44
    2   CoreFoundation                      0x025efcf5 __NSFastEnumerationMutationHandler + 165
    3   Foundation                          0x01e47f03 -[NSConcreteMapTable countByEnumeratingWithState:objects:count:] + 66
    4   CoreFoundation                      0x0253d77f -[__NSFastEnumerationEnumerator nextObject] + 143
    5   SpriteKit                           0x01d009f2 +[SKTextureAtlas(Internal) findTextureNamed:] + 232
    6   SpriteKit                           0x01cf709c __26-[SKTexture loadImageData]_block_invoke + 1982
    7   SpriteKit                           0x01d34d09 _Z14SKSpinLockSyncPiU13block_pointerFvvE + 40
    8   SpriteKit                           0x01cf6898 -[SKTexture loadImageData] + 228
    9   SpriteKit                           0x01cf65d9 __51+[SKTexture preloadTextures:withCompletionHandler:]_block_invoke + 241
    10  libdispatch.dylib                   0x02b117b8 _dispatch_call_block_and_release + 15
    11  libdispatch.dylib                   0x02b264d0 _dispatch_client_callout + 14
    12  libdispatch.dylib                   0x02b14eb7 _dispatch_root_queue_drain + 291
    13  libdispatch.dylib                   0x02b15127 _dispatch_worker_thread2 + 39
    14  libsystem_c.dylib                   0x02de1e72 _pthread_wqthread + 441
    15  libsystem_c.dylib                   0x02dc9daa start_wqthread + 30
)
libc++abi.dylib: terminating with uncaught exception of type NSException

4 个答案:

答案 0 :(得分:4)

我偶尔会得到同样的例外。它已经存在了一段时间,我一直在努力查明它数周。

我怀疑是由于预加载纹理可能会发生,无论是手动还是由Sprite Kit自动触发,同时其他一些代码会导致纹理被加载或访问。

我已经减少了preloadTextures:调用了一个,但我仍然遇到问题,只是不那么经常。我试图执行Selector:onMainThread:每当我运行一个选择器来访问或加载完成块中的图像(或者只是内部)或在不同线程上运行的其他代码。

在我将用户界面代码移动到主线程(它是从完成处理程序调用)之后,我今天整天都没有遇到此崩溃。我不能100%确定这是否能解决这个问题。

我希望这会有所帮助。肯定有些挑剔,如果你做po 0x1459da60(在lldb的命令窗口中,使用异常提供的地址),你会看到它正在被修改的SKTextureAtlas纹理列表。我希望这可以帮助您确定问题的来源。

答案 1 :(得分:4)

我可以在sprite kit方法中告诉它一个sprite kit bug:

preloadTextures: withCompletionHandler:

我能解决这个问题的唯一方法就是彻底删除这个方法。 根据apple docs,如果访问size属性,纹理也会被加载。 所以我的解决方法就是做到这一点:

for (SKTexture *texture in self.texturesArray) {
    texture.size;
}

它不漂亮但它有效!

答案 2 :(得分:2)

当我尝试预加载两个简单的动画时,我遇到了同样的问题。我试图在字典中预加载动画,并准备好通过字符串键调用它们。这是我试过的

-(void)setupAnimDict {
    animDict = [[NSMutableDictionary alloc] init];

    [animDict setObject:[self animForName:@"blaze" frames:4] forKey:@"blaze"];
    [animDict setObject:[self animForName:@"flame" frames:4] forKey:@"flame"];
}

-(SKAction *)animForName:(NSString *)name frames:(int)frames {
    NSArray *animationFrames = [self setupAnimationFrames:name base:name num:frames];
    SKAction *animationAction = [SKAction animateWithTextures:animationFrames     timePerFrame:0.10 resize:YES restore:NO];
    return [SKAction repeatActionForever:animationAction];
}

-(NSArray *)setupAnimationFrames:(NSString *)atlasName base:(NSString *)baseFileName num:(int)numberOfFrames {

    [self preload:baseFileName num:numberOfFrames];

    NSMutableArray *frames = [NSMutableArray arrayWithCapacity:numberOfFrames];
    SKTextureAtlas *atlas = [SKTextureAtlas atlasNamed:atlasName];
    for (int i = 0; i < numberOfFrames; i++) {
        NSString *fileName = [NSString stringWithFormat:@"%@%01d.png", baseFileName, i];
        [frames addObject:[atlas textureNamed:fileName]];
    }

    return frames;
}

-(void)preload:(NSString *)baseFileName num:(int)numberOfFrames {

    NSMutableArray *frames = [NSMutableArray arrayWithCapacity:numberOfFrames];

    for (int i = 0; i < numberOfFrames; i++) {
        NSString *fileName = [NSString stringWithFormat:@"%@%01d.png", baseFileName, i];
        [frames addObject:[SKTexture textureWithImageNamed:fileName]];
    }

    [SKTexture preloadTextures:frames withCompletionHandler:^(void){}];
}

当我调用setupDict方法时,我有时会遇到与您相同的错误。问题是我的两个动画的预加载相互碰撞。我通过改变

来摆脱错误
[SKTexture preloadTextures:frames withCompletionHandler:^(void){}];

if ([baseFileName isEqualToString:@"blaze"]) {
        [SKTexture preloadTextures:frames withCompletionHandler:^{
            [self setupFlame];
        }];
    } else {
        [SKTexture preloadTextures:frames withCompletionHandler:^(void){}];
    }

以便在我尝试预加载另一个之前完成第一次预加载。

我不知道这是不是你的问题,但如果是让我们知道的话。

答案 3 :(得分:1)

在Xcode 6.3 beta / Swift 1.2中,我仍然发生了同样的事情。这是一个对我有用的临时修复。

SKTextureAtlas.preloadTextureAtlases([SKTextureAtlas(named: "testAtlas")], withCompletionHandler: {
    dispatch_async(dispatch_get_main_queue(), {
        handler()
    })
})

我实际上将它包装在一个函数中,以便所有预加载都通过它。这样一来,如果在SpriteKit方面得到修复,或者这种方法存在重大缺陷,我可以删除调度。