Confused Confused - 1 month ago 6
Swift Question

How to clear SKSpriteNodes from memory?

I make a bunch of sprites from the gameScene and other objects, all by calling a function that creates instances of a subclass of SKSpriteNode.

eg, from GameScene, like this:

let sizee = CGSize(width: 100, height: 100)
let posi = CGPoint(x: 200, y: 300)

func createSprite(){
let new = Circle(color: SKColor.blue, size: sizee , position: posi)
addChild(new)
new.zPosition = 2
}


from within Circle, I remove each instance after its done a bit of animating:

import SpriteKit

class Circle: SKSpriteNode {

let fade = SKAction.fadeAlpha(to: 0.5, duration: 2)
let myScale = SKAction.scaleX(to: 3, duration: 2)
let die = SKAction.removeFromParent()

override init(texture: SKTexture?, color: UIColor, size: CGSize) {
super.init(texture: texture, color: color, size: size)
}
convenience init(color: UIColor, size: CGSize, position: CGPoint) {
self.init(color: color, size: size)
self.position = position
self.run(SKAction.sequence([fade, die]))
self.run(myScale)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

}


Is this enough to ensure that these are getting released from memory?

Or do I have to do something else to flush them from the game world and memory?

Answer

Few weeks ago Apple have update this page:

Swift uses Automatic Reference Counting (ARC) to track and manage your app’s memory usage. In most cases, this means that memory management “just works” in Swift, and you do not need to think about memory management yourself. ARC automatically frees up the memory used by class instances when those instances are no longer needed.

Reference counting only applies to instances of classes. Structures and enumerations are value types, not reference types, and are not stored and passed by reference.

There is a way to prevent an instance from deinitialising, and thus creating a leak. This is called a Strong Reference Cycle. Take a look at this answer where you can understand in detail what I mean now.

Looking to your code I would have done this:

self.run(SKAction.group([fade, myScale], completion:  {
     [weak self] in
     guard let strongSelf = self else { return }
     strongSelf.removeFromParent()
}))