Быстро, как вернуть память в нормальное состояние после удаления SKScene?

Я создал простую игру с SpriteKit, но каждый раз, когда я запускаю игру, использование памяти в симуляторе увеличивается примерно на 30 мб, но никогда не уменьшается, когда игра заканчивается.

Когда я запускаю игру более чем в десять раз, симулятор становится все медленнее и медленнее и в конечном итоге падает.

В этой простой игре у меня есть два контроллера и gamescene:

MainController вызывает GameViewController с помощью кнопки

В GameViewController инициализируется gamecene следующим образом:

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
    }
  }
}

В GameScene viewController является свойством

var viewController:GameViewController? = GameViewController()

срабатывание segue происходит следующим образом:

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

Я также попытался применить методы удаления в Deanit в GameScene:

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

По-прежнему не работает

Ответ 1

Ваш GameViewController имеет сильную ссылку на ваш GameScene. И ваш GameScene имел сильную ссылку на ваш GameViewController. Это приводит к сильному эталонному циклу, что означает, что ни один объект не будет освобожден.

Вам нужно объявить свойство viewController в вашем GameScene слабым.

weak var viewController:GameViewController? = GameViewController()

Ответ 2

Использование Swift 3, Xcode 8 и iOS 10. После того, как вы отказались от сильных ссылок, позаботились о SKTextures и т.д. Уровень памяти не восстановился после увольнения сцены и возврата в "menu" viewController. Я использовал:

override func sceneDidLoad() {...}

Это доступно в iOS 10, но мне нужна совместимость с iOS 8 и 9, поэтому я изменено на старшее:

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

Помимо совместимости со старыми версиями iOS, оказывается, что уровень памяти падает после увольнения сцены. Это был сюрприз. Я пропускаю, вероятно, некоторые утечки, но он работает на меня. Надеюсь, это поможет кому-то.