self.view?.presentScene:在展开可选值时意外发现 nil (Swift)

Posted

技术标签:

【中文标题】self.view?.presentScene:在展开可选值时意外发现 nil (Swift)【英文标题】:self.view?.presentScene: unexpectedly found nil while unwrapping an Optional value (Swift) 【发布时间】:2015-11-05 11:50:50 【问题描述】:

我正在尝试切换场景,但我的应用程序崩溃并出现此错误:

crash
crash
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb) 

这是我切换场景的代码:

func switchscenes() 

    if display >= 2 
        Player.removeFromParent()
        PlayerRight.removeFromParent()
        PlayerLeft.removeFromParent()
        fireHair.removeFromParent()
        fireHairRight.removeFromParent()
        fireHairLeft.removeFromParent()
        imageRightView.removeFromSuperview()
        imageLeftView.removeFromSuperview()
                                    println("crash")
        var gameplayScene:SKScene = GamePlay(size: self.size)
                                    println("crash")
        self.view?.presentScene(gameplayScene)
                                    println("crash")
        display = 0

    

然后在视图中确实加载了:

timer5 = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("switchscenes"), userInfo: nil, repeats: true)

它打印了两次崩溃但不是第三次显​​示

self.view?.presentScene(gameplayScene) 

是错误的原因。我怎样才能解决这个问题?

编辑:

GamePlay.swift 代码:

import SpriteKit
import Foundation
import UIKit
import iAd

//Collisions
struct PhysicsCategory 
static let Enemy : UInt32 = 1
static let Player : UInt32 = 2
static let PlayerRight : UInt32 = 3
static let PlayerLeft : UInt32 = 4
static let SuperBlock : UInt32 = 5


var transition:SKTransition = SKTransition.fadeWithDuration(0.5)


var superblockRandomizer = NSTimeInterval()
var timer8 : NSTimer!
var playerVelocity :CGFloat!

class GamePlay: SKScene, SKPhysicsContactDelegate 

var SuperBlock = SKShapeNode()



var redRandom : CGFloat = 1
var greenRandom : CGFloat = 1
var blueRandom : CGFloat = 1


//Highscore Variable
var Highscore = Int()

var fontsize : CGFloat = 20

//Score
var Score : Int = 0
var ScoreLabel = UILabel()

//Snow
var snow = SKEmitterNode(fileNamed: "SnowShower")

//Rain
var rain = SKEmitterNode(fileNamed: "RainShower")

//Fire Hair
var fireHair = SKEmitterNode(fileNamed: "FireHair")

//Fire Hair Right
var fireHairRight = SKEmitterNode(fileNamed: "FireHair")

//Fire Hair Left
var fireHairLeft = SKEmitterNode(fileNamed: "FireHair")

//Main Character
var Player = SKSpriteNode(imageNamed: "mainPlayer.png")

//Right-far character
var PlayerRight = SKSpriteNode(imageNamed: "mainPlayer.png")

//Left-far character
var PlayerLeft = SKSpriteNode(imageNamed: "mainPlayer.png")


//Holding vs Tapping Movement of Player
var isTouching = false

var touchXPosition:CGFloat = 0


override func didMoveToView(view: SKView) 
    /* Setup your scene here */


    playerVelocity = (size.width / 25)

    let controller = self.view?.window?.rootViewController as? GameViewController

    // Preload a new iAd
    interAd = ADInterstitialAd()
    interAd.delegate = controller

    adLoaded = false

    superblockRandomizer = NSTimeInterval(arc4random_uniform(5) + 5)

    let spawnBlock = SKAction.sequence([SKAction.runBlock(spawnEnemies), SKAction.waitForDuration(0.3)])
    runAction(SKAction.repeatActionForever(spawnBlock))

    let runScore = SKAction.sequence([SKAction.runBlock(scoreCounter), SKAction.waitForDuration(0.1)])
    runAction(SKAction.repeatActionForever(runScore))

    let spawnSuperBlock = SKAction.sequence([SKAction.waitForDuration(superblockRandomizer), SKAction.runBlock(spawnSuperBlocks)])
    runAction(SKAction.repeatActionForever(spawnSuperBlock))

    snow.particleBirthRate = 15

    fireHair.particleBirthRate = 200

    fireHairRight.particleBirthRate = 200

    fireHairLeft.particleBirthRate = 200

    rain.particleBirthRate = 100

    //Highscore
    var HighscoreDefault = NSUserDefaults.standardUserDefaults()

    if (HighscoreDefault.valueForKey("Highscore") != nil) 
        Highscore = HighscoreDefault.valueForKey("Highscore") as! NSInteger
    
    else 
        Highscore = 0
    

    //Collisions/Physics
    physicsWorld.contactDelegate = self

    //Background Color
    scene?.backgroundColor = UIColor.blackColor()

    //Player coordinates
    Player.position.x = size.width * 0.5
    Player.position.y = size.height / 3

    //Setting Player Sizes
    Player.size.width = size.width * 0.11
    Player.size.height = size.width * 0.11
    PlayerRight.size.width = size.width * 0.11
    PlayerRight.size.height = size.width * 0.11
    PlayerLeft.size.width = size.width * 0.11
    PlayerLeft.size.height = size.width * 0.11

    //Setting hair position range
    fireHair.particlePositionRange = CGVector(dx: size.width * 0.11, dy: 0)
    fireHairRight.particlePositionRange = CGVector(dx: size.width * 0.11, dy: 0)
    fireHairLeft.particlePositionRange = CGVector(dx: size.width * 0.11, dy: 0)

    //Setting snow position range
    snow.particlePositionRange = CGVector(dx: size.width, dy: 0)

    //Initial position of player
    Player.position = CGPoint(x: Player.position.x, y: Player.position.y)
    //Initial position of far-right player
    PlayerRight.position = CGPoint(x: Player.position.x + size.width, y: Player.position.y)
    //Initial position of far-left player
    PlayerLeft.position = CGPoint(x: Player.position.x - size.width, y: Player.position.y)

    //Adding Physics/Collisions to Player
    Player.physicsBody = SKPhysicsBody (rectangleOfSize: Player.size)
    Player.physicsBody?.affectedByGravity = false
    Player.physicsBody?.categoryBitMask = PhysicsCategory.Player
    Player.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy | PhysicsCategory.SuperBlock
    Player.physicsBody?.dynamic = false

    //Adding Physics/Collisions to PlayerRight
    PlayerRight.physicsBody = SKPhysicsBody (rectangleOfSize: PlayerRight.size)
    PlayerRight.physicsBody?.affectedByGravity = false
    PlayerRight.physicsBody?.categoryBitMask = PhysicsCategory.PlayerRight
    PlayerRight.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy | PhysicsCategory.SuperBlock
    PlayerRight.physicsBody?.dynamic = false

    //Adding Physics/Collisions to PlayerLeft
    PlayerLeft.physicsBody = SKPhysicsBody (rectangleOfSize: PlayerRight.size)
    PlayerLeft.physicsBody?.affectedByGravity = false
    PlayerLeft.physicsBody?.categoryBitMask = PhysicsCategory.PlayerLeft
    PlayerLeft.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy | PhysicsCategory.SuperBlock
    PlayerLeft.physicsBody?.dynamic = false

    //Making Players visible
    self.addChild(Player)
    self.addChild(PlayerRight)
    self.addChild(PlayerLeft)
    self.addChild(fireHair)
    self.addChild(fireHairRight)
    self.addChild(fireHairLeft)

    if size.height <= 569 
        fontsize = 20
    
    else if size.height >= 569 

        fontsize = 25
    

    //Making Score Visible
    ScoreLabel.text = "\(Score)"
    ScoreLabel = UILabel(frame: CGRect(x: 0, y: 0, width: fontsize*5, height: fontsize))
    ScoreLabel.font = UIFont(name: ScoreLabel.font.fontName, size: fontsize)
    ScoreLabel.textColor = UIColor.whiteColor()
    self.view?.addSubview(ScoreLabel)


func scoreCounter() 
    //Setting score
    Score += 1
    ScoreLabel.text = "\(Score)"



func didBeginContact(contact: SKPhysicsContact) 
    var firstBody : SKPhysicsBody = contact.bodyA
    var secondBody : SKPhysicsBody = contact.bodyB

    //Checking for Player to enemy collisions
    if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.Player))
        CollisionWithEnemy(firstBody.node as! SKShapeNode, Player: secondBody.node as! SKSpriteNode)

    
    else if (firstBody.categoryBitMask == PhysicsCategory.Player) && (secondBody.categoryBitMask == PhysicsCategory.Enemy) 
        CollisionWithEnemy2(firstBody.node as! SKSpriteNode, Enemy: secondBody.node as! SKShapeNode)
    
    //Checking for PlayerRight to enemy collisions
    if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.PlayerRight))
        CollisionWithEnemy(firstBody.node as! SKShapeNode, Player: secondBody.node as! SKSpriteNode)

    
    else if (firstBody.categoryBitMask == PhysicsCategory.PlayerRight) && (secondBody.categoryBitMask == PhysicsCategory.Enemy) 
        CollisionWithEnemy2(firstBody.node as! SKSpriteNode, Enemy: secondBody.node as! SKShapeNode)
    
    //Checking for PlayerLeft to enemy collisions
    if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.PlayerLeft))
        CollisionWithEnemy(firstBody.node as! SKShapeNode, Player: secondBody.node as! SKSpriteNode)

    
    else if (firstBody.categoryBitMask == PhysicsCategory.PlayerLeft) && (secondBody.categoryBitMask == PhysicsCategory.Enemy) 
        CollisionWithEnemy2(firstBody.node as! SKSpriteNode, Enemy: secondBody.node as! SKShapeNode)
    

    if SuperBlock.position.y > size.height / 2 
    //Checking for enemy to enemy collisions
    if ((firstBody.categoryBitMask == PhysicsCategory.SuperBlock) && (secondBody.categoryBitMask == PhysicsCategory.Enemy))
        SuperBlockWithEnemy(firstBody.node as! SKShapeNode, Enemy: secondBody.node as! SKShapeNode)

    
    else if (firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.SuperBlock) 
        SuperBlockWithEnemy2(firstBody.node as! SKShapeNode, SuperBlock: secondBody.node as! SKShapeNode)
    
    

    //Checking for Player to superblock collisions
    if ((firstBody.categoryBitMask == PhysicsCategory.SuperBlock) && (secondBody.categoryBitMask == PhysicsCategory.Player))
        CollisionWithSuper(firstBody.node as! SKShapeNode, Player: secondBody.node as! SKSpriteNode)

    
    else if (firstBody.categoryBitMask == PhysicsCategory.Player) && (secondBody.categoryBitMask == PhysicsCategory.SuperBlock) 
        CollisionWithSuper2(firstBody.node as! SKSpriteNode, SuperBlock: secondBody.node as! SKShapeNode)
    

    //Checking for PlayerRight to superblock collisions
    if ((firstBody.categoryBitMask == PhysicsCategory.SuperBlock) && (secondBody.categoryBitMask == PhysicsCategory.PlayerRight))
        CollisionWithSuper(firstBody.node as! SKShapeNode, Player: secondBody.node as! SKSpriteNode)

    
    else if (firstBody.categoryBitMask == PhysicsCategory.PlayerRight) && (secondBody.categoryBitMask == PhysicsCategory.SuperBlock) 
        CollisionWithSuper2(firstBody.node as! SKSpriteNode, SuperBlock: secondBody.node as! SKShapeNode)
    

    //Checking for PlayerLeft to superblock collisions
    if ((firstBody.categoryBitMask == PhysicsCategory.SuperBlock) && (secondBody.categoryBitMask == PhysicsCategory.PlayerLeft))
        CollisionWithSuper(firstBody.node as! SKShapeNode, Player: secondBody.node as! SKSpriteNode)

    
    else if (firstBody.categoryBitMask == PhysicsCategory.PlayerLeft) && (secondBody.categoryBitMask == PhysicsCategory.SuperBlock) 
        CollisionWithSuper2(firstBody.node as! SKSpriteNode, SuperBlock: secondBody.node as! SKShapeNode)
    



func CollisionWithEnemy(Enemy: SKShapeNode, Player: SKSpriteNode) 

    //Highscore
    var ScoreDefault = NSUserDefaults.standardUserDefaults()
    ScoreDefault.setValue(Score, forKey: "Score")
    ScoreDefault.synchronize()


    if (Score > Highscore) 
        var HighscoreDefault = NSUserDefaults.standardUserDefaults()
        HighscoreDefault.setValue(Score, forKey: "Highscore")
    

    var gameOver:SKScene = GameOverScene(size: self.size)
    ScoreLabel.removeFromSuperview()
    Player.removeFromParent()

    self.view?.presentScene(gameOver, transition: transition)





func CollisionWithEnemy2(Player: SKSpriteNode, Enemy: SKShapeNode) 

    //Highscore
    var ScoreDefault = NSUserDefaults.standardUserDefaults()
    ScoreDefault.setValue(Score, forKey: "Score")
    ScoreDefault.synchronize()

    if (Score > Highscore) 
        var HighscoreDefault = NSUserDefaults.standardUserDefaults()
        HighscoreDefault.setValue(Score, forKey: "Highscore")
    

    var gameOver:SKScene = GameOverScene(size: self.size)
    ScoreLabel.removeFromSuperview()
    Player.removeFromParent()




    self.view?.presentScene(gameOver, transition: transition)





func SuperBlockWithEnemy(SuperBlock: SKShapeNode, Enemy: SKShapeNode) 

    Enemy.removeFromParent()


func SuperBlockWithEnemy2(Enemy: SKShapeNode, SuperBlock: SKShapeNode) 

    Enemy.removeFromParent()


func CollisionWithSuper(SuperBlock: SKShapeNode, Player: SKSpriteNode) 

    //Highscore
    var ScoreDefault = NSUserDefaults.standardUserDefaults()
    ScoreDefault.setValue(Score, forKey: "Score")
    ScoreDefault.synchronize()


    if (Score > Highscore) 
        var HighscoreDefault = NSUserDefaults.standardUserDefaults()
        HighscoreDefault.setValue(Score, forKey: "Highscore")
    

    var gameOver:SKScene = GameOverScene(size: self.size)
    ScoreLabel.removeFromSuperview()
    Player.removeFromParent()
    self.view?.presentScene(gameOver, transition: transition)




func CollisionWithSuper2(Player: SKSpriteNode, SuperBlock: SKShapeNode) 
    //Highscore
    var ScoreDefault = NSUserDefaults.standardUserDefaults()
    ScoreDefault.setValue(Score, forKey: "Score")
    ScoreDefault.synchronize()

    if (Score > Highscore) 
        var HighscoreDefault = NSUserDefaults.standardUserDefaults()
        HighscoreDefault.setValue(Score, forKey: "Highscore")
    

    var gameOver:SKScene = GameOverScene(size: self.size)
    ScoreLabel.removeFromSuperview()
    Player.removeFromParent()
    self.view?.presentScene(gameOver, transition: transition)



override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) 
    /* Called when a touch begins */

    isTouching = true

    for touch in (touches as! Set<UITouch>) 
        let location = touch.locationInNode(self)

        touchXPosition = location.x

    



override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) 
    isTouching = false


func spawnSuperBlocks() 

    superblockRandomizer = NSTimeInterval(arc4random_uniform(5) + 5)


    //Randomizing width of blocks
    var blockWidth = Int(arc4random_uniform(UInt32(size.width / 3)) + UInt32(size.width / 3))

    //Min and Max position of blocks
    var minPosition : UInt32 = UInt32(blockWidth / 2)
    var maxPosition : UInt32 = UInt32(size.width - CGFloat(blockWidth / 2))

    //Randomizing Block Position
    var blockXPosition = arc4random_uniform(maxPosition - minPosition) + minPosition

    //Making Blocks
    SuperBlock = SKShapeNode(rectOfSize: CGSize(width: blockWidth, height: Int(size.height / 12)))
    SuperBlock.position = CGPointMake (CGFloat(blockXPosition),  CGFloat(size.height+size.height / 5))

    //Coloring Blocks
    redRandom = CGFloat(arc4random_uniform(200) + 56)
    greenRandom = CGFloat(arc4random_uniform(200) + 56)
    blueRandom = CGFloat(arc4random_uniform(200) + 56)


    SuperBlock.fillColor = SKColor(red: redRandom / 255, green: greenRandom / 255, blue: blueRandom / 255, alpha: 1)
    SuperBlock.lineWidth = 0

    //Moving Blocks
    let action = SKAction.moveToY(-50, duration: 1)

    //Removing blocks once off screen
    let actionDone = SKAction.removeFromParent()

    //Running the above actions
    SuperBlock.runAction(SKAction.sequence([action, actionDone]))


    //Physics/Collisions
    SuperBlock.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize (width: blockWidth, height: 50))
    SuperBlock.physicsBody?.categoryBitMask = PhysicsCategory.SuperBlock
    SuperBlock.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy
    SuperBlock.physicsBody?.affectedByGravity = false
    SuperBlock.physicsBody?.dynamic = true

    //Adding enemy to scene
    self.addChild(SuperBlock)


func spawnEnemies() 

    //Randomizing width of blocks
    var blockWidth = Int(arc4random_uniform(UInt32(size.width / 3)) + UInt32(size.width / 4))

    //Min and Max position of blocks
    var minPosition : UInt32 = UInt32(blockWidth / 2)
    var maxPosition : UInt32 = UInt32(size.width - CGFloat(blockWidth / 2))

    //Randomizing Block Position
    var blockXPosition = arc4random_uniform(maxPosition - minPosition) + minPosition


    var sideblockPositionMin = UInt32(blockWidth / 2)

    var sideblockPositionMax = UInt32(size.width - CGFloat(blockWidth / 2))


    var randomizer2 = arc4random_uniform(10)

    if randomizer2 == 5 
        blockXPosition = sideblockPositionMin
    
    else if randomizer2 == 7 
        blockXPosition = sideblockPositionMax
    
    else 

    

    //Making Blocks
    var Enemy = SKShapeNode(rectOfSize: CGSize(width: blockWidth, height: Int(size.height / 100)))
    Enemy.position = CGPointMake (CGFloat(blockXPosition),  CGFloat(size.height+size.height / 12))

    //Coloring Blocks
    Enemy.fillColor = SKColor.whiteColor()

    //Moving Blocks
    let action = SKAction.moveToY(-50, duration: 1.5)

    //Removing blocks once off screen
    let actionDone = SKAction.removeFromParent()

    //Running the above actions
    Enemy.runAction(SKAction.sequence([action, actionDone]))

    //Physics/Collisions
    Enemy.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize (width: blockWidth, height: 1))
    Enemy.physicsBody?.categoryBitMask = PhysicsCategory.Enemy
    Enemy.physicsBody?.affectedByGravity = false
    Enemy.physicsBody?.dynamic = true

    //Adding enemy to scene
    self.addChild(Enemy)



func spawn() 



override func update(currentTime: CFTimeInterval) 
    /* Called before each frame is rendered */

    Player.position = CGPoint(x: Player.position.x, y: Player.position.y)

    PlayerRight.position = CGPoint(x: Player.position.x + size.width, y: Player.position.y)

    PlayerLeft.position = CGPoint(x: Player.position.x - size.width, y: Player.position.y)

    fireHair.position = CGPoint(x: Player.position.x, y: Player.position.y - Player.size.height / 1.5)

    fireHairRight.position = CGPoint(x: Player.position.x + size.width, y: Player.position.y - Player.size.height / 1.5)

    fireHairLeft.position = CGPoint(x: Player.position.x - size.width, y: Player.position.y - Player.size.height / 1.5)

    if isTouching 
        if touchXPosition > self.size.width / 2 
            // move character to the right.
            Player.position.x += playerVelocity

        
        if touchXPosition < self.size.width / 2 
            // move character to the left.
            Player.position.x -= playerVelocity

        
    

    if Player.position.x < 0 
        Player.position.x = Player.position.x + size.width
        PlayerRight.position.x = Player.position.x + size.width
        PlayerLeft.position.x = Player.position.x - size.width
    
    if Player.position.x > size.width 
        Player.position.x = Player.position.x - size.width
        PlayerRight.position.x = Player.position.x + size.width
        PlayerLeft.position.x = Player.position.x - size.width
    


【问题讨论】:

有人知道如何解决这个问题吗? 还是想不通 添加了一个赏金,无法解决这个问题,我的应用因为这个问题被拒绝了。 你能添加GamePlay.swift吗?代码。在这里看不到任何问题。 为您添加了 Cagatay。 【参考方案1】:

几天后终于弄明白了。我想在开发的早期制作一个凉爽的雨/雪效果,但我最终决定不这样做。结果我仍然有几行与雨和雪相关的代码,但它们正在加载我已删除的 nil SKEmitterNode(文件名为:)。

【讨论】:

在未来,这种类型的问题很容易通过以下方式解决:a)查看堆栈回溯以查找问题发生的位置,然后失败 b)检查代码中的强制展开 - 其中之一他们是罪魁祸首。

以上是关于self.view?.presentScene:在展开可选值时意外发现 nil (Swift)的主要内容,如果未能解决你的问题,请参考以下文章

PresentScene 内存:removeAllChildren 是不是传播?

为什么self.view.frame和self.view.bounds在设备旋转时有所不同?

iOS 7 状态栏和 self.view.frame 和 self.view.bounds

self.view 有限制吗?

self.view.layer.contents 和 self.view.backgroundColor

防止 CGAffineTransfromScale 在 self.view 之外缩放