Загрузка SKTexutre Crash изменена при перечислении

У меня проблемы со следующим кодом, который загружает SKTexture, вызывая его size. Код случайным образом дает сбой примерно в 1 из каждых 100 запусков в строке, где вызывается размер. Есть и другие методы 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. Но я думаю, что должна быть какая-то работа вокруг. Что вы думаете, ребята?

Спасибо,

Гаррен


person user2821647    schedule 25.03.2015    source источник


Ответы (1)


Это ошибка

Это определенно похоже на ошибку в 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

person logancautrell    schedule 09.04.2015