Knight0fDragon Knight0fDragon - 12 days ago 5
Swift Question

SKTextureAtlas no longer sharing textures in iOS 10

It seems that when pulling textures from a texture atlas, I am now generating new textures instead of using the same texture across different sprites with iOS 10. On iOS 9, this works as expected. Is anyone else experiencing this issue? Perhaps there is a step I missed that is now a part of iOS 10.

Notes: I created a sample project and created a new atlas, then just dragged spaceship in @1x, I have also tried preloading, and that did nothing as well.

Code:

let atlas = SKTexturAtlas(named:"Sprites")
var texture = atlas.textureNamed("Spaceship")
print("\(Unmanaged.passUnretained(texture)),\(Unmanaged.passUnretained(texture).toOpaque())")

texture = atlas.textureNamed("Spaceship")
print("\(Unmanaged.passUnretained(texture)),\(Unmanaged.passUnretained(texture).toOpaque())")


Edit: To get around issues of comparison, I use the description property to compare if 2 textures are equal. For this to work though, you can't be using 2 atlases that each contain a texture with an exact name and size. I will never hit this situation, but for anybody out there looking for help, keep this in mind.

Answer

To get around this issue, I had to come up with a way to cache the textures so that it doesn't duplicate:

private var textureCache = [String: SKTexture]()
extension SKTextureAtlas
{
    func texturesWithNames(_ names:[String]) -> [SKTexture]
    {
        var textures = [SKTexture]()
        names.forEach({textures.append(textureNamed($0))})
        return textures
    }
    func cachedTextureWithName(_ name:String) -> SKTexture
    {
        if  textureCache[name] == nil
        {

            textureCache[name] = textureNamed(name)
        }

        return textureCache[name]!
    }
    func cachedTexturesWithNames(_ names:[String]) -> [SKTexture]
    {
        var textures = [SKTexture]()
        names.forEach({textures.append(cachedTextureWithName($0))})
        return textures
    }
    func clearCache()
    {
        textureCache = [String: SKTexture]()
    }
}


extension SKTexture
{

    var name : String
    {
        return self.description.slice(start: "'",to: "'")!
    }


}