加载SKTexutre枚举时发生崩溃

问题描述:

我在下面的代码中调用它的大小加载SKTexture时出现问题。代码在调用大小的行中每100次运行中随机崩溃约1次。还有一些其他SKTexture方法用于预加载图像,但它们也会更频繁地导致崩溃!我使用TextureAtlases,并通过这种方法防止所有的SKTexure负载发生崩溃。加载SKTexutre枚举时发生崩溃

/* add image to dictionary thread-safe */ 
-(SKTexture*) getThreadSafeDictionaryContainImageOtherwiseLoadAndReturn:(NSString*) imageToLoad andForceLoad:(BOOL) forceLoad{ 

    // to control the enviroment where the image dictionary is modified, go ahead and lock it down with an NSLock 
    [self.dictionaryModificationLock lock]; 

    SKTexture *toReturn = nil; 
    CGSize size = CGSizeZero; 

    // first, ignore duplicate loads by looking for the image in an NSDictionary called "allImages" 
    if ((toReturn = [self.allImages objectForKey:imageToLoad])){ 
     // have the image to return already loaded 

    }else{ 
     // grab the SKTexture and force it to load by requesting it's size 
     SKTexture *texture = [SKTexture textureWithImageNamed:imageToLoad]; 
     if (forceLoad) 
      size = texture.size; // crashes here! 

     [self.allImages setObject:texture forKey:imageToLoad]; 
     toReturn = texture; 
    } 

    [self.dictionaryModificationLock unlock]; // unlock the NSLock 
    return toReturn; 
} 

这里的崩溃报告的样子:

Fatal Exception: NSGenericException 
*** Collection <NSConcreteMapTable: 0x1c059ff0> was mutated while being enumerated. 

0 CoreFoundation __exceptionPreprocess + 126 
2 CoreFoundation -[NSException name] 
3 Foundation -[NSConcreteMapTable countByEnumeratingWithState:objects:count:] + 56 
4 CoreFoundation -[__NSFastEnumerationEnumerator nextObject] + 110 
5 SpriteKit +[SKTextureAtlas(Internal) findTextureNamed:] + 284 
6 SpriteKit __26-[SKTexture loadImageData]_block_invoke + 1654 
7 SpriteKit SKSpinLockSync(int*, void() block_pointer) + 104 
8 SpriteKit -[SKTexture loadImageData] + 302 
9 SpriteKit -[SKTexture size] + 42 

我已经找到了一些其他线程说这是SpriteKit问题。但我认为必须有一些解决方法。你们有什么感想?

感谢,

盖伦

它是一种错误

这肯定看起来像SpriteKit的错误。你可以尝试预先加载图像,它可能会结束一个单独的代码路径。其可能的预加载将有助于防止这种情况发生。

https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Sprites/Sprites.html#//apple_ref/doc/uid/TP40013043-CH9-SW21

阿特拉斯

如果你没有准备好,可以考虑使用一个纹理图集,并在那里预加载您的所有资产。

https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Sprites/Sprites.html#//apple_ref/doc/uid/TP40013043-CH9-SW15

锁定

一个侧面说明,我不认为这将解决您的崩溃可言,但使用@synchronized为锁定更多的语义。

而不是有一个NSLock,只是将当前的锁代码包在@synchronized(self)。如果您与代码的其他部分发生争执并锁定自己,则可以创建单独的id textureLockObject属性。

Apple可以并将优化@synchronized代码比使用NSLocks更多。

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW3