加载SKTexture Crash在枚举时发生变异

时间:2015-03-25 01:01:36

标签: ios sktexture

我遇到以下代码问题,它通过调用其大小来加载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的问题。但我认为必须有一些解决方法。你们觉得怎么样?

谢谢,

盖伦

1 个答案:

答案 0 :(得分: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可以并且将比使用NSLocks更优化@synchronized代码。

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