this is the error that i see when present SKScene
, this error occurs randomly and are not able to replicate
* Terminating app due to uncaught exception 'NSGenericException', reason: '* Collection < NSConcreteMapTable: 0x1459da60 > was mutated while being enumerated.'
what's happen?
tell me if you need any other info
thanks
EDIT:
*** 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
I get the same exception on occasion. It's been around for a while and I've been trying to pinpoint it for weeks.
My suspicion is that it may occur due to preloading textures, either manually or triggered automatically by Sprite Kit while at the same time some other code causes textures to be loaded or accessed.
I have reduced my preloadTextures: calls to a single one but I still get the issue, just less often. I have tried to performSelector:onMainThread: whenever I run a selector that accesses or loads images (or just might internally) from within a completionBlock or other code that runs on a different thread.
I haven't had this crash the entire day today after I moved my user interface code to the main thread (it was called from a completion handler). I can't say 100% for sure whether this fixed it though.
I hope this helps a little. There's definitely something finicky going on, and if you do po 0x1459da60
(in lldb's command window, using the address provided by the exception) you'll see that it is the SKTextureAtlas texture list that is being modified. I hope that helps you pinpoint where the issue is coming from on your side.
From what I can tell this a sprite kit bug in the sprite kit method:
preloadTextures: withCompletionHandler:
The only way I was able to fix this was by removing this method completely.
According to apple docs the textures also get loaded if you access the size
property.
So my workaround is just to do exactly that:
for (SKTexture *texture in self.texturesArray) {
texture.size;
}
It's not pretty but it works!
I had the same problem, when I tried to preload two simple animations. I tried to preload the animations in a dictionary and have them ready to be called via a string key. Here is what I tried
-(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){}];
}
When I called the setupDict method I sometimes got the same error as you. The problem was that preloading of my two animations run into each other. I got rid of the error by changing the
[SKTexture preloadTextures:frames withCompletionHandler:^(void){}];
to
if ([baseFileName isEqualToString:@"blaze"]) {
[SKTexture preloadTextures:frames withCompletionHandler:^{
[self setupFlame];
}];
} else {
[SKTexture preloadTextures:frames withCompletionHandler:^(void){}];
}
so that the first preloading was done before I attempted to preload the other.
I don't know if this is your problem, but if it is let us know.
Same thing still happening for me in Xcode 6.3 beta / Swift 1.2. Here is a temporary fix that has worked for me.
SKTextureAtlas.preloadTextureAtlases([SKTextureAtlas(named: "testAtlas")], withCompletionHandler: {
dispatch_async(dispatch_get_main_queue(), {
handler()
})
})
I actually wrapped this in a function so that all preloads route through it. That way if it gets fixed on the SpriteKit side, or if there are major flaws with this approach, I can remove the dispatch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With