Reputation: 251
I need to deallocate gamescene after the player have finished a level so that the memory is available to load another level of my game. If I don't do that, I have a crash of my app because of memory issues.
I have followed the indications given there:
Swift: Deallocate GameScene after transition to new scene?
But unfortunately, it doesn't work for me. I get an error "Could not cast value 'UIView' to 'SKView' in my GameViewController class. Here is my whole code:
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()
}
}
I call the different functions nextSceneAction1()
, nextSceneAction2()
, and nextSceneAction3()
from my other classes with:
let controller1 = GameViewController()
controller1.nextSceneAction1()
or
let controller2 = GameViewController()
controller2.nextSceneAction1()
When the new scene is loaded, I get this error: "Could not cast value of type 'UIView' to 'SKView'. Do you know what is wrong with this code?
By the way, I'm open with all other possibilities to clean old scene from memory before loading a new one so that there is no memory crash during the life of the app.
Upvotes: 1
Views: 365
Reputation: 10674
In general a SKScene automatically deallocates once you transition to a new scene, unless you have a memory leak, so usually you don't have to do anything in particular to free memory.
To see if your scene has deallocated you can add the deinit method
func deinit {
print("scene did deallocate")
}
If this method gets called when you change scenes you know everything correctly deallocated, if it doesn't get called you have a memory leak.
Also you code is faulty, you are creating a new GameViewController instance everytime you change scene instead of accessing the current instance.
let controller2 = GameViewController() // creates new instance of GameViewController
controller2.nextSceneAction1()
You normally only load your 1st scene from your GameViewController and than all other scene changes can be done directly in the SKScene you are in. Don't bother using the GameViewController for this.
In your current SKScene you can change to a new scene like this (e.g from GameScene to 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)
}
}
Hope this helps
Upvotes: 3