我遇到以下代码问题,它通过调用其大小来加载SKTexture。代码在调用大小的行中每100次运行中随机崩溃大约1次。还有一些其他SKTexture方法可以预加载图像,但它们也会更频繁地导致崩溃!我使用TextureAtlases并通过此方法防止所有SKTexure加载发生崩溃。
/* 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的问题。但我认为必须有一些解决方法。你们觉得怎么样?
谢谢,
盖伦
答案 0 :(得分:0)
这是一个错误
这绝对看起来像是SpriteKit中的一个错误。您可以尝试首先预加载图像,它可能会在单独的代码路径中结束。它可能的预加载将有助于防止这种情况发生。
<强>阿特拉斯强>
如果您还没有,请考虑使用纹理图集并在那里预加载所有资源。
<强>锁定强>
附注,我不认为这会解决你的崩溃问题,但使用@synchronized进行锁定更具语义性。
不要使用NSLock,只需将当前锁定代码包装在@synchronized(self)
中。如果您与代码中同时锁定自身的其他部分发生争用,则可以创建单独的id textureLockObject
属性。
Apple可以并且将比使用NSLocks更优化@synchronized代码。