NSGenericException原因Collection <NSConcreteMapTable:xxx>
这是我目前SKScene
看到的错误,这个错误是随机发生的,不能复制
*由于未捕获exception'NSGenericException',原因:'* Collection <NSConcreteMapTable:0x1459da60>被枚举时发生了变异。
发生了什么?
告诉我,如果你需要任何其他信息
谢谢
编辑:
*** 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
我有时会得到同样的例外。 这已经有一段时间了,我一直在努力查明几个星期。
我怀疑是由于预加载纹理,手动或由Sprite Kit自动触发,而同时其他代码导致纹理加载或访问。
我已经减less了我的preloadTextures:调用一个单一的,但我仍然得到这个问题,不太经常。 我试图执行select器:onMainThread:每当我运行一个select器访问或加载图像(或只是可能内部)在一个completionBlock或其他代码运行在不同的线程。
在将用户界面代码移到主线程(从完成处理程序调用它)后,我今天没有发生这种崩溃。 我不能肯定地说100%是否固定它。
希望这会有帮助。 肯定有一些挑剔的事情发生,如果你使用po 0x1459da60
(在lldb的命令窗口中,使用exception提供的地址),你会发现它是被修改的SKTextureAtlas纹理列表。 我希望能帮助你找出问题出在哪里。
从我可以告诉这个精灵套件方法中的精灵套件错误:
preloadTextures: withCompletionHandler:
我能够解决这个问题的唯一方法就是彻底删除这个方法。 根据苹果文档纹理也得到加载,如果您访问size
属性。 所以我的解决方法就是做到这一点:
for (SKTexture *texture in self.texturesArray) { texture.size; }
它不漂亮,但它的作品!
我有同样的问题,当我试图预载两个简单的animation。 我尝试在字典中预加载animation,并准备通过string键调用它们。 这是我试过的
-(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方法时,我有时会得到和你一样的错误。 问题是,我的两个animation预加载彼此。 我通过改变摆脱了错误
[SKTexture preloadTextures:frames withCompletionHandler:^(void){}];
至
if ([baseFileName isEqualToString:@"blaze"]) { [SKTexture preloadTextures:frames withCompletionHandler:^{ [self setupFlame]; }]; } else { [SKTexture preloadTextures:frames withCompletionHandler:^(void){}]; }
以便在我试图预先加载另一个之前完成第一次预加载。
我不知道这是否是你的问题,但如果是让我们知道。
在Xcode 6.3 beta / Swift 1.2中同样的事情仍然在发生。 这是一个临时的解决scheme,为我工作。
SKTextureAtlas.preloadTextureAtlases([SKTextureAtlas(named: "testAtlas")], withCompletionHandler: { dispatch_async(dispatch_get_main_queue(), { handler() }) })
我实际上把它包装在一个函数中,以便所有的预加载都通过它。 这样,如果它在SpriteKit方面得到修复,或者如果这种方法存在重大缺陷,我可以删除调度。