【问题标题】:In swift, how to get memory back to normal after an SKScene is removed?快速,删除 SKScene 后如何使内存恢复正常?
【发布时间】:2015-06-17 13:18:26
【问题描述】:

我用 SpriteKit 创建了一个简单的游戏,但是每次运行游戏时,模拟器中的内存使用量都会增加大约 30mb,但游戏结束后不会减少。

当我运行游戏十次以上时,模拟器变得越来越慢,最终崩溃。

在这个简单的游戏中,我有两个控制器和一个游戏场景:

MainController 通过触发按钮调用 GameViewController

在 GameViewController 中,游戏场景是这样初始化的:

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)

我也试过将 remove 方法放入 GameScene 中的 deinit 中:

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

还是不行

【问题讨论】:

标签: swift memory sprite-kit skscene


【解决方案1】:

您的GameViewController 强烈引用您的GameScene。而你的GameScene 强烈引用了你的GameViewController。这会导致强引用循环,这意味着两个对象都不会被释放。

您需要在 GameScene 中将 viewController 属性声明为 weak。

weak var viewController:GameViewController? = GameViewController()

【讨论】:

  • 好的,我在游戏结束后使用了dismissViewControllerAnimated而不是performSegueWithIdentifier,没有removeAllChildren和removeAllActions方法,似乎“奏效”了……每次游戏启动时内存都会以非常小的数量增加...怎么会这样?
  • @FanZhang 你能解释一下你是怎么做到的吗?我现在遇到同样的问题有一段时间了,我真的希望能解决...
  • 没什么特别的,只是在GameScene中实例化GameViewController:weak var viewController:GameViewController? = GameViewController() ,并在游戏结束时运行 self.viewController?.dismissViewControllerAnimated(true, completion: nil) 。
  • 谢谢!我的 viewcontroller 已经对 SKView 有一个弱引用,但是在我的 SKScene 中,有一个对它所在的 viewcontroller 的强引用,通过使它成为一个弱变量,我的内存使用量在弹出后又下降了。
  • 哇,这疯狂的巨大差异!这应该被标记为这个问题的正确答案。
【解决方案2】:

使用 Swift 3、Xcode 8 和 iOS 10。 在避免强引用、处理 SKTextures 等之后,在关闭场景并返回“菜单”视图控制器后内存级别没有恢复。 我正在使用:

override func sceneDidLoad() {...}

这在 iOS 10 中可用,但我希望与 iOS 8&9 兼容,这就是我选择的原因 更改为旧版本:

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

除了与旧 iOS 版本兼容之外,事实证明,在关闭场景后内存级别会下降。这是一个惊喜。我可能错过了一些泄漏,但它对我有用。 我希望它可以帮助某人。

【讨论】:

  • 你能创建最小的可验证示例来证明这种泄漏吗?
  • @Whirlwind 抱歉,我试过了,但我做不到。泄漏仪器显示了一些与“SKAction.animate”相关的泄漏,我还没有解决。我虽然这是问题所在,但现在,只更改为“didMove”,内存问题就消失了。
猜你喜欢
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 2019-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多