2017-04-11 10 views
2

SpriteKitゲームを含むアプリケーションを開発しています。ゲームを終了した後のSpriteKit保持メモリ

enter image description here

私はモーダルプレゼンテーションを使用してビューコントローラからゲームを提示しています:私が気づいたことは、私が起動し、ゲームを閉じた後、メモリは以下のグラフに示すように増加し続けるということです。だから問題は: シーンをメモリから完全に削除する方法はありますか?

View Controllerの閉じるボタンをタップして閉じます。 scene.quitGame()メソッドは、基本的にすべてのノードやアクションなどを解放します。理想的な世界では、SKSceneを完全に取り除く魔法のコマンドがあるので、それを行う必要はありません。

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

編集:私は次のコードでの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 

EDIT 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") 


} 

EDIT 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 
} 
+0

このビューコントローラは繰り返し表示され、却下されますか?または、常にView Controllerが起動していますか?シーンは、ビューコントローラが設定しているデリゲートを定義していますか? –

+0

シーンを保持しているビューコントローラーが表示され、閉じられています。 –

+0

私はデリゲートを定義しませんでした。それはどのように機能するのですか? –

答えて

5

、あなたがcapture listsを使用する必要があります。それはすべてが詳細に説明されたため

func createHerosAction(duration: Double = 5.0){ 

     run(SKAction.repeatForever(
      SKAction.sequence([ 

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

、それは大きな話題ですが、私はあなたが私が投稿したリンクを読み始めることをお勧め「ARCの仕組み」、「キャプチャリストとは何か」から始まり、脆弱なキーワードと未所有のキーワードを抽出します。私はこのサイトについてこれまで数回書いたことがありますが、これは大きな話題ですので、今回はスキップします:)

+0

あなたのすばらしいヘルプ@Whirlwindに感謝します。これはまだ私の問題を解決しませんが、私たちはそれを締結しています。 EDIT 3を参照してください。 –

+0

@ JPAquino私自身のプロジェクトでこれを再作成し、あなたの 'createHerosAction'は、移行後にリーク手段のシーンを割り当て解除できません。まあ、通常の 'SKTransition'です。そのため、あなたは '' {'unowned self} ''を必要としています...私はあなたの新しい編集を見ていきます...ところで、なぜ '' SKIIeage'を作るために '' SKTexture'を作るために '' UIImage' 'テクスチャから? 'SKTexture(named:)'と一緒に行くだけです。あなたは 'SKSpriteNode(imageNamed:)'と一緒に行くこともできますが、そのメソッドは実績がありません(http://stackoverflow.com/a/30448038/3402095)... – Whirlwind

+0

@JPAquino 'その所有者も所有していません。クロージャーの内側で強い自己を使うとき、クロージャーはそれを捕らえることを覚えておく必要があります。 – Whirlwind

0

私はメモリ内にViewControllerを保持している内部SpriteKitリークを信じています。我々は、SpriteKitがviewControllerを却下した後、SceneとSKViewを保持するように見えることを発見しました。

私たちのケースでは、私たちはゲームが終わったときに、私たちが画面上でゲームを提示した直後に無シーンを提示し始めました。あなたのコメントに基づいて

// Remove the game scene to stop game code and free up memory 
    if let skView = view as? SKView { 
     skView.presentScene(nil) 
    } 
+0

私にとってはうまくいかないようです。私はこれをゲームシーンのquitGame()メソッドとviewControllerのquitメソッドに追加しようとしましたが、メモリリークは変更されません。 –

+1

presentScene(nil)は、SKViewでsceneプロパティをnilに設定するだけです。他のいくつかのインスタンスがシーンへの強い参照を持っている場合、リークは残っています...シーンが漏れたオブジェクトである場合: – Whirlwind

+0

"self"に対する強い参照を保持できるクロージャがありますか?実行(ブロック)アクションなどのように? – BadgerBadger

関連する問題