In swift, how to get memory back to normal after an SKScene is removed?

3k views Asked by At

I created a simple game with SpriteKit, however every time I run the game, the memory usage in simulator increases about 30mb, but never decreases when the game is finished.

When I run the game over ten times the simulator gets slower and slower and eventually crashes.

In this simple game I have two controllers and a gamescene:

MainController calls GameViewController via a button triggered

In GameViewController, gamescene is initialised in this way:

class GameViewController: UIViewController
{

  var skView:SKView!

  var scene:GameScene!

  override func viewDidLoad() {

      super.viewDidLoad()
      scene = GameScene(size: view.bounds.size)
      skView = view as SKView
      skView.ignoresSiblingOrder = true
      scene.scaleMode = .ResizeFill

      scene.viewController = self
      skView.presentScene(scene)

  }

//with a prepareForSegue deinitialises the scene and skview:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    if segue.identifier == "GameFinished"{

        scene.removeAllActions()
        scene.removeAllChildren()
        scene.removeFromParent()
        scene = nil

        skView.presentScene(nil)
        skView = nil

        let target = segue.destinationViewController as MainController
    }
  }
}

In the GameScene, viewController is a property

var viewController:GameViewController? = GameViewController()

the segue is triggered with this:

self.viewController!.performSegueWithIdentifier("GameFinished", sender: nil)

I've also tried putting remove methods into deinit in GameScene:

  deinit{
    self.removeAllActions()
    self.removeAllChildren()
  }

Still wouldn't work

2

There are 2 answers

5
Epic Byte On

Your GameViewController has a strong reference to your GameScene. And your GameScene had a strong reference to your GameViewController. This leads to a strong reference cycle, which means that neither objects will be deallocated.

You need to declare your viewController property in your GameScene as weak.

weak var viewController:GameViewController? = GameViewController()
2
user2888102 On

Using Swift 3, Xcode 8 and iOS 10. After avoiding strong references, taken care of SKTextures, etc. memory level didn't recover after dismissing the scene and returning to the "menu" viewController. I was using:

override func sceneDidLoad() {...}

This is available in iOS 10 but I wanted iOS 8&9 compatibility that's why I've changed to the older:

override func didMove(to view: SKView) {...}

Beside getting compatible with older iOS versions, it turns out that the memory level drops after dismissing the scene. This was a surprise. I'm missing probably some leaks but it's working for me. I hope it helps someone.