命中致命错误:在展开可选值 (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 个物体(a
、b
、c
)发生碰撞,并且碰撞逻辑适用于所有 3 个物体,则 sprite kit 将执行 2 次碰撞检查:
a
和b
然后是 b
和 c
的实体
您正在移除碰撞时的物体:
第一次检测:身体 a
和 b
被打开,身体 a
和 b
被移除
第二次检测:只剩下主体c
,因为a
和b
已被删除。这意味着 secondBody
或 firstBody
现在为零。于是报错了
尝试将您的代码更改为以下内容,它应该可以解决问题:
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 && 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的主要内容,如果未能解决你的问题,请参考以下文章
AVCaptureSession 运行时崩溃。致命错误:在展开可选值 (lldb) 时意外发现 nil
如何修复:“致命错误:在展开可选值 (lldb) 时意外发现 nil”