命中致命错误:在展开可选值 (lldb) 时意外发现 nil

Posted

技术标签:

【中文标题】命中致命错误:在展开可选值 (lldb) 时意外发现 nil【英文标题】:Hit fatal error: unexpectedly found nil while unwrapping an Optional value (lldb) 【发布时间】:2015-05-04 12:57:39 【问题描述】:

我编写了一个简单的游戏,在第一次碰撞时出现以下错误:

这是我的代码:

func didBeginContact(contact: SKPhysicsContact) 

    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask 
        firstBody = contact.bodyA
        secondBody = contact.bodyB

     else 
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    

    if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
        (secondBody.categoryBitMask & PhysicsCategory.naboj != 0)) 
            projectileDidCollideWithMonster(firstBody.node as SKSpriteNode, monster: secondBody.node as SKSpriteNode)

    


【问题讨论】:

崩溃在哪一行? projectileDidCollideWithMonster(firstBody.node as SKSpriteNode, monster: secondBody.node as SKSpriteNode) 我猜 firstBody 或 node 然后可以为零。如果在这一行上断点,firstBody.node 和 secondBody.node 有什么值? 【参考方案1】:

我之前也遇到过这个问题

基本上,当您展开物理体时(这通常发生在显示secondBody.node! 的行),会发生以下情况:

    如果您有 3 个物体(abc)发生碰撞,并且碰撞逻辑适用于所有 3 个物体,则 sprite kit 将执行 2 次碰撞检查:

    一个有身体ab 然后是 bc 的实体

    您正在移除碰撞时的物体:

    第一次检测:身体 ab 被打开,身体 ab 被移除

    第二次检测:只剩下主体c,因为ab 已被删除。这意味着 secondBodyfirstBody 现在为零。于是报错了

尝试将您的代码更改为以下内容,它应该可以解决问题:

var firstBody: SKPhysicsBody?
var secondBody: SKPhysicsBody?

if (firstBody!.node! != nil && secondBody!.node! != nil) 
       if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
                (secondBody.categoryBitMask & PhysicsCategory.Projectile != 0)) 
                projectileDidCollideWithMonster(secondBody.node!, monster: firstBody.node!)
        

【讨论】:

if (firstBody!.node! != nil &amp;&amp; secondBody!.node! != nil) 将在任何这些强制展开的值为 nil 时崩溃...最好使用 if let(或 nil 合并)来测试对象是否存在。 这是对所发生情况的一个很好的解释。谢谢你的解释。【参考方案2】:

您使用的是 swift 1 还是 1.2?

试试

if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
    (secondBody.categoryBitMask & PhysicsCategory.naboj != 0)) 

    if let firstNode = firstBody.node as? SKSprintNode,
       let secondNode = secondBody.node as? SKSprinteNode 

       projectileDidCollideWithMonster(firstNode, monster: secondNode)
    

【讨论】:

【参考方案3】:

试试这个方法:

if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
    (secondBody.categoryBitMask & PhysicsCategory.naboj != 0)) 
    if(firstBody.node != nil && secondBody.node != nil ) 
        projectileDidCollideWithMonster(firstBody.node as SKSpriteNode, monster: secondBody.node as SKSpriteNode) 

【讨论】:

【参考方案4】:

好吧,这花了我一段时间才弄明白,但最后我明白了。我尝试了大多数其他我可以在网上找到的解决方案,但运气不佳。我不得不以艰难的方式弄清楚。如果找到 nil,您需要做的是提供中断/返回选项。因为大多数情况下,当两个相同的碰撞同时触发时会发生此错误。

我所做的是创建一个 if else 语句以在出现 nil 时返回该函数。

func didBeginContact(contact: SKPhysicsContact) 

var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody

if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask 
    firstBody = contact.bodyA
    secondBody = contact.bodyB

 else 
    firstBody = contact.bodyB
    secondBody = contact.bodyA


if ((firstBody.categoryBitMask & PhysicsCategory.Monster != 0) &&
    (secondBody.categoryBitMask & PhysicsCategory.naboj != 0)) 
// new part
    if (firstBody.node == nil || secondBody.node == nil)
    return

else 
 projectileDidCollideWithMonster(firstBody.node as SKSpriteNode, monster: secondBody.node as SKSpriteNode)

我希望这会有所帮助。 同样重要的是,通过在 if 而不是 else 中使用 return 语句,将其视为期待 nil。

【讨论】:

以上是关于命中致命错误:在展开可选值 (lldb) 时意外发现 nil的主要内容,如果未能解决你的问题,请参考以下文章

致命错误:在展开可选值 (lldb) 时意外发现 nil

致命错误:在展开可选值 (lldb) 时意外发现 nil

AVCaptureSession 运行时崩溃。致命错误:在展开可选值 (lldb) 时意外发现 nil

如何修复:“致命错误:在展开可选值 (lldb) 时意外发现 nil”

swift:致命错误:在展开可选值(lldb)时意外发现 nil,线程 1

Swift 错误致命错误:在展开可选值时意外发现 nil