2016-08-04 60 views
0

我需要在玩家完成關卡後取消分配gamescene,以便內存可以載入我的遊戲的另一個關卡。如果我不這樣做,由於內存問題,我的應用程序崩潰。Swift,SpriteKit:釋放一個Gamescene並重新分配一個新的

我按照給那裏的適應症:

Swift: Deallocate GameScene after transition to new scene?

但不幸的是,它並沒有爲我工作。我在GameViewController類得到一個錯誤「無法施展價值‘的UIView’到‘SKView’這裏是我的整個代碼:

import Foundation 
import UIKit 
import SpriteKit 

class GameViewController: UIViewController { 

    var scene1: SKScene? 
    var scene2: SKScene? 
    var scene3: SKScene? 
    var skView: SKView? 


    func nextSceneAction1() { 

     scene2 = nil 
     scene3 = nil 

     skView! = self.view as! SKView 
     skView!.showsFPS = true 
     skView!.showsNodeCount = true 

     /* Sprite Kit applies additional optimizations to improve rendering performance */ 
     skView!.ignoresSiblingOrder = true 

     scene1 = TransitionSigns(size: skView!.frame.size) 
     scene1!.size.width = 2048 
     scene1!.size.height = 1536 


     /* Set the scale mode to scale to fit the window */ 
     scene1!.scaleMode = .AspectFill 

     let transition = SKTransition.revealWithDirection(.Right, duration: 2) 

     scene1!.scaleMode = .AspectFill 
     skView!.presentScene(scene1!, transition: transition) 
    } 

    func nextSceneAction2() { 

     scene1 = nil 
     scene3 = nil 

     let skView = self.view as! SKView 
     skView.showsFPS = true 
     skView.showsNodeCount = true 

     /* Sprite Kit applies additional optimizations to improve rendering performance */ 
     skView.ignoresSiblingOrder = true 

     scene2 = TransitionSigns(size: skView.frame.size) 
     scene2!.size.width = 2048 
     scene2!.size.height = 1536 


     /* Set the scale mode to scale to fit the window */ 
     scene2!.scaleMode = .AspectFill 

     let transition = SKTransition.revealWithDirection(.Right, duration: 2) 

     scene2!.scaleMode = .AspectFill 
     skView.presentScene(scene2!, transition: transition) 
    } 

    func nextSceneAction3() { 

     scene1 = nil 
     scene2 = nil 

     let skView = self.view as! SKView 
     skView.showsFPS = true 
     skView.showsNodeCount = true 

     /* Sprite Kit applies additional optimizations to improve rendering performance */ 
     skView.ignoresSiblingOrder = true 

     scene3 = TransitionSigns(size: skView.frame.size) 
     scene3!.size.width = 2048 
     scene3!.size.height = 1536 


     /* Set the scale mode to scale to fit the window */ 
     scene3!.scaleMode = .AspectFill 

     let transition = SKTransition.revealWithDirection(.Right, duration: 2) 

     scene3!.scaleMode = .AspectFill 
     skView.presentScene(scene3!, transition: transition) 
    } 


    override func viewWillLayoutSubviews() { 
     // Configure the view. 

     let skView = self.view as! SKView 
     skView.showsFPS = true 
     skView.showsNodeCount = true 

     /* Sprite Kit applies additional optimizations to improve rendering performance */ 
     skView.ignoresSiblingOrder = true 

     let scene = MainView(size: skView.frame.size) 
     scene.size.width = 2048 
     scene.size.height = 1536 

     /* Set the scale mode to scale to fit the window */ 
     scene.scaleMode = .AspectFill 

     skView.presentScene(scene) 
    } 

    override func shouldAutorotate() -> Bool { 
     return true 
    } 

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask { 
     if UIDevice.currentDevice().userInterfaceIdiom == .Phone { 
      return UIInterfaceOrientationMask.AllButUpsideDown 
     } else { 
      return UIInterfaceOrientationMask.All 
     } 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Release any cached data, images, etc that aren't in use. 
    } 

    override func prefersStatusBarHidden() -> Bool { 
     return true 
    } 


    override func viewDidLoad() { 
     super.viewDidLoad() 

    } 

    override func viewDidDisappear(animated: Bool) { 

     self.view.removeFromSuperview() 
    } 

    override func viewWillDisappear(animated: Bool){ 
     self.view.removeFromSuperview() 
    } 
} 

我所說的不同的功能nextSceneAction1()nextSceneAction2(),並從我的其他類nextSceneAction3()與:

let controller1 = GameViewController() 
controller1.nextSceneAction1() 

let controller2 = GameViewController() 
controller2.nextSceneAction1() 

當新場景被加載時,我得到這個錯誤:「無法投型的價值‘的UIView’到'SKView'。你知道這段代碼有什麼問題嗎?

順便說一句,我打開所有其他的可能性來清理舊的場景從內存中加載一個新的,以便在應用程序的生命期間沒有內存崩潰。

回答

2

一般來說,一旦你轉換到一個新的場景,SKScene會自動釋放,除非你有內存泄漏,所以通常你不需要做任何特別的操作來釋放內存。

要查看您的場景已釋放,你可以添加DEINIT方法

func deinit { 
     print("scene did deallocate") 
    } 

如果這種方法被調用時,你改變了自己知道的一切正確釋放的場面,如果它不會叫你有記憶泄漏。

此外,您的代碼有問題,您每次更改場景而不是訪問當前實例時都會創建一個新的GameViewController實例。

let controller2 = GameViewController() // creates new instance of GameViewController 
controller2.nextSceneAction1() 

您通常只從GameViewController和比所有其他的場景變化可以直接在SKScene你是在做加載您第一次現場。不要打擾使用GameViewController這一點。

在當前的SKScene可以(例如,從GameScene到MenuScene)更改爲新的場景是這樣

class GameScene: SKScene { 

     ... 


     func loadMenuScene() { 

      let menuScene = MenuScene(size: self.size) // use size of current scene   
      let transition = Some SKTransition 
      view?.presentScene(menuScene, withTransition: transition) 
     } 
} 

希望這有助於

+0

感謝,似乎一切從spritesheets紋理然而,在留記憶,即使場景已從屏幕上消失。我已經成功地減少了內存使用量,將所有2040X2048紋理替換爲160字節10X10像素的非常小的PNG空白紋理。當一個場景消失並被一個新場景取代時,這減少了我幾百MB遊戲的內存使用量... – PGibouin

+0

這是正常行爲。 SpriteKit緩存紋理以提升性能。我不會釋放它們,讓SpriteKit爲你做。 – crashoverride777

+0

要添加到此。轉到您的SKScenes並使用打印語句添加deinit(請參閱更新的答案)方法。如果deinit被調用,您知道整個場景已正確釋放,如果它沒有內存泄漏。這樣就更容易看到發生了什麼,因爲SpriteKit在背景上做了很多東西,例如紋理緩存。 – crashoverride777

相關問題