1

我在使用以下代码时遇到问题,该代码通过调用 SKTexture 的大小来加载它。代码在调用 size 的行每 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 的问题。但我认为必须有一些解决方法。你们有什么感想?

谢谢,

加伦

4

1 回答 1

0

它是一个错误

这绝对看起来像 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

于 2015-04-09T12:59:41.343 回答