当我尝试在GameViewController中使用它时,我的GameScene返回nil

时间:2014-11-08 16:20:39

标签: ios swift fatal-error null optional

我正在使用Swift创建一个基本的太空飞船游戏,一切运行良好,直到我尝试添加一个功能,每当用户刷卡时,飞船就会向上移动。我添加了一个UISwipeGestureRecognizer并将其与我的GameViewController中的IBAction连接,然后我打算在我的GameScene中调用一个方法来使太空船向上移动。

import UIKit
import SpriteKit

extension SKNode {
    class func unarchiveFromFile(file : NSString) -> SKNode? {
        if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
            var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
            var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)

            archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
            let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as GameScene
            archiver.finishDecoding()
            return scene
        } else {
            return nil
        }
    }
}
class GameViewController: UIViewController {

    let scene: GameScene!

    @IBAction func swipeUp(sender: UISwipeGestureRecognizer){
        scene.movePlaneUp()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
            let skView = self.view as SKView
            skView.ignoresSiblingOrder = true
            scene.scaleMode = .AspectFill

            skView.presentScene(scene)
        }
    }

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

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

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

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

所有内容都会编译并且应用程序会运行,但是,每当我尝试向上滑动时,都会出现致命错误:在行中打开可选值时意外地发现nil

scene.movePlaneUp()

我理解错误的发生是因为场景的值是nil,但是如何使场景实际上具有GameScene的值?

这是我的GameScene代码:

import SpriteKit

class GameScene: SKScene {
    override func didMoveToView(view: SKView) {
        let bg = SKSpriteNode(imageNamed: "Background")
        bg.size = self.frame.size
        bg.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
        self.addChild(bg)
        let sprite = SKSpriteNode(imageNamed: "Spaceship")
        sprite.xScale = 0.6
        sprite.yScale = 0.5
        sprite.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMinY(self.frame)+CGRectGetMaxY(sprite.frame))
        sprite.name = "spaceship"
        self.addChild(sprite)
    }
    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        var t = touches.allObjects[0]
        let location = t.locationInNode(self)
        let action = SKAction.moveToX(location.x, duration:0.1)
        let n = self.childNodeWithName("spaceship")
        n?.runAction(action)
        let bullet = SKSpriteNode(imageNamed: "Spaceship")
        bullet.xScale = 0.05
        bullet.yScale = 0.05
        bullet.position = CGPoint(x: location.x, y: 200+bullet.position.y)
        bullet.runAction(SKAction.moveToY(1000, duration: 0.75))
        self.addChild(bullet)
    }
    func movePlaneUp(){
        let n = childNodeWithName("spaceship")
        n?.removeAllActions()
        let action = SKAction.moveBy(CGVector(dx: 0, dy: 100), duration: 1)
        n?.runAction(action)
    }
}

2 个答案:

答案 0 :(得分:0)

我意识到我遇到错误的原因是因为我从未向场景分配过任何东西。我通过改变

解决了我的问题
let scene: GameScene!

let myScene: GameScene!

然后我将viewDidLoad改为

override func viewDidLoad() {
    super.viewDidLoad()
    if let scene = GameScene.unarchiveFromFile("GameScene") as? GameScene {
        let skView = self.view as SKView
        skView.ignoresSiblingOrder = true
        scene.scaleMode = .AspectFill
        skView.presentScene(scene)
        myScene = scene
    }
}

然后实际为myScene分配了一个值

答案 1 :(得分:0)

我知道这有点晚了...如果你使用self.scene = scene它也会有效。这是由于使用scene创建的if let scene var,会覆盖if let范围内具有相同名称的任何其他变量。你现在可能已经知道了(因为它已经创建了两年了):)但是,我希望它对这门语言的新手有用。