我离开游戏后SpriteKit保留内存

JP *_*ino 2 memory memory-leaks memory-management sprite-kit swift

所以我正在开发一个包含SpriteKit游戏的应用程序.我注意到的是,在我开始和关闭游戏后,内存不断增加,如下图所示:

在此输入图像描述

我使用模态演示文稿从View Controller呈现游戏.所以问题是:有没有办法从内存中完全删除场景?

我点击视图控制器上的关闭按钮以关闭它.该scene.quitGame()方法基本上释放所有节点,动作等.在一个理想的世界中,我甚至不需要做任何这样的事情,因为会有一个魔法命令SKScene完全消除.

@IBAction func quit(_ sender: UIButton) {
    scene.quitGame()
    scene.removeFromParent()
    self.removeFromParentViewController()
    self.dismiss(animated: true, completion: nil)
    scene = nil
}
Run Code Online (Sandbox Code Playgroud)

编辑:我使用以下代码从viewDidLoad呈现场景:

scene = GameScene(size: view.bounds.size)
let skView = view as! SKView
skView.showsFPS = false
skView.showsNodeCount = false
skView.ignoresSiblingOrder = true
scene.scaleMode = .resizeFill
if let heroImage2 = heroImage2, let myImage = myImage, let monsterImage = monsterImage{
    scene.addPicture(img: heroImage2, myImage: myImage,monsterImage: monsterImage, bigMonsterImage: bigMonsterImage!)
}
skView.presentScene(scene)
scene.viewController = self
Run Code Online (Sandbox Code Playgroud)

编辑2 - 我注释掉了对这种方法的调用,其中包括重复永久动作,泄漏似乎消失了

   func createHerosAction(duration: Double = 5.0){
        run(SKAction.repeatForever(
            SKAction.sequence([
                SKAction.run(addHero),
                SKAction.wait(forDuration: duration)
                ])
        ), withKey:"createHeros")
    }



func addHero() {
    // Create sprite
    if(heroImage == nil){
        heroImage = UIImage(named: "hero")
    }

    let Texture = SKTexture(image: heroImage!)
    let hero = SKSpriteNode(texture:Texture)
    hero.size.width = size.width * 0.17
    hero.size.height = hero.size.width
    hero.name = "hero"
    hero.zPosition = 2

    let heroSide = arc4random_uniform(2)

    hero.physicsBody = SKPhysicsBody(rectangleOf: hero.size) // 1
    hero.physicsBody?.isDynamic = true // 2
    hero.physicsBody?.categoryBitMask = PhysicsCategory.Hero // 3
    hero.physicsBody?.contactTestBitMask = PhysicsCategory.Projectile // 4
    hero.physicsBody?.collisionBitMask = PhysicsCategory.None // 5

    let actualY = random(min: size.height*0.3 + hero.size.height/2 + size.height * 0.12, max: size.height - hero.size.height/2 - size.height * 0.15)

    let pointRightOfScreen = CGPoint(x: size.width + hero.size.width/2, y: actualY)
    let pointLeftOfScreen = CGPoint(x:  -hero.size.width/2, y: actualY)

    if(heroSide == 0){
        hero.position = pointRightOfScreen
    }else{
        hero.position = pointLeftOfScreen
    }

    addChild(hero)

    let actualDuration = random(min: CGFloat(2.0), max: CGFloat(5.0))

    var actionMove = SKAction()

    if(heroSide == 0){
        actionMove = SKAction.move(to: pointLeftOfScreen, duration: TimeInterval(actualDuration))
    }else{
        actionMove = SKAction.move(to: pointRightOfScreen, duration: TimeInterval(actualDuration))
    }

    let numberOfUpsAndDown = random(min: CGFloat(1.0), max: CGFloat(10.0))
    let variance = random(min: CGFloat(-70.0), max: CGFloat(70.0))


    let mvHero = moveHeroUpAndDown(node: hero, variance: variance,duration: actualDuration/numberOfUpsAndDown)

    let actionMoveDone = SKAction.removeFromParent()


    let loseLifeAction = loseLife(node: hero)

    hero.run(SKAction.sequence([actionMove, loseLifeAction, actionMoveDone]), withKey: "moveHero")
    hero.run(mvHero, withKey: "UpAndDown")


}
Run Code Online (Sandbox Code Playgroud)

编辑3:泄漏似乎是在上面调用的SKAction上.我删除此操作后,泄漏停止.

   func loseLife(node: SKSpriteNode) -> SKAction{

    let loseALifeAction = SKAction.run(){

        if(self.gamePaused == false){
            self.playSound(fileName: "losesound.wav")

            if(self.lives > 0){
                self.updateLives(newValue: self.lives - 1, lostLife: true)
                //self.lives -= 1
            }

            print("lives: \(self.lives)")

            if(self.lives <= 0){
                print("hit me")
                node.run(self.loseGame())
            }
        }
    }
    return loseALifeAction
}
Run Code Online (Sandbox Code Playgroud)

Whi*_*ind 5

根据您的评论,您应该使用捕获列表:

func createHerosAction(duration: Double = 5.0){

        run(SKAction.repeatForever(
            SKAction.sequence([

                SKAction.run {[unowned self] in
                    self.addHero()
                },
                SKAction.wait(forDuration: duration)
                ])
        ), withKey:"createHeros")
    }
Run Code Online (Sandbox Code Playgroud)

这是一个很大的话题,但我建议你开始阅读我发布的链接,因为它从"如何使用ARC","什么是捕获列表"开始详细解释了这些弱关键字.我已经写了几次这个,以及这个网站上的许多其他人,这是一个很大的话题,所以这次我会跳过:)