ios - swift ,SpriteKit : Deallocate a Gamescene et reallocate a new one

标签 ios swift memory

我需要在玩家完成一个关卡后释放游戏场景,以便内存可用于加载我的游戏的另一个关卡。如果我不这样做,我的应用程序就会因内存问题而崩溃。

我已按照此处给出的指示进行操作:

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’。你知道这段代码有什么问题吗?

顺便说一句,我对在加载新场景之前从内存中清除旧场景的所有其他可能性持开放态度,这样应用程序的生命周期内就不会出现内存崩溃。

最佳答案

一般情况下,一旦您转换到新场景,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)
      }  
 }

希望对你有帮助

关于ios - swift ,SpriteKit : Deallocate a Gamescene et reallocate a new one,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38774683/

相关文章:

ios - 将 NSArray 中的 TableView 项目分组到 Swift 中的 JSON 响应中返回

ios - 将RTF文件解析为NSArray- objective-c

ios - 在ios的文本字段中添加无法编辑的加号( objective-c )

IOS:使用 NSTimer 更新 UITableViewCell 中的标签

ios - 来自外部源的 iframe 内容未加载到 iOS 上的本地 HTML 文件中

swift - "as?"、 "as!"和 "as"之间有什么区别?

java - 从 C# 编辑 Java 应用程序的内存

ios - Visual Studio for mac iOS Storyboard无法正常工作

c - 子例程写入其调用例程的堆栈是否安全?

java - Java中,String.format()的实现是否考虑了String的不可变性?