展开可选值时意外发现 nil - boxNode.addChildNode(importedBox!)

Unexpectedly found nil while unwrapping an Optional value - boxNode.addChildNode(importedBox!)

我有一些代码运行 for 循环来创建 2 个对象并将它们填充到 boxArray 中,然后将它们添加到场景中。第一次通过代码可以很好地创建一个框,但是在 addBox(num: Int) 函数创建第二个框的过程中,它因主题行中的错误而崩溃。这条线负责 "boxNode.addChildNode(importedBox!)" 但我不知道为什么,因为它是第一次工作。

    importedSceneBox = SCNScene(named: "art.scnassets/boxObject.dae")

    for var i = 0; i <= 1; ++i {

        let boxNode = self.addBox(i)
        boxArray.append(boxNode)
        theScene.rootNode.addChildNode(boxArray[i])
    }

func addBox(num: Int) -> SCNNode{

    let boxNode = SCNNode()
    let importedBox = importedSceneBox.rootNode.childNodeWithName("pCube4", recursively: false)
    importedBox?.scale = SCNVector3Make(70, 70, 70)
    boxNode.addChildNode(importedBox!)
    boxNode.position = SCNVector3Make(5, 100, 3)
    let collisionBox = SCNBox(width: 5.0, height: 5.0, length: 5.0, chamferRadius: 0)
    boxNode.physicsBody?.physicsShape = SCNPhysicsShape(geometry: collisionBox, options: nil)
    boxNode.physicsBody = SCNPhysicsBody.dynamicBody()
    boxNode.physicsBody?.mass = 1
    boxNode.physicsBody?.restitution = 0.8
    boxNode.physicsBody?.damping = 0.5
    boxNode.name = "dice" + String(num)
    boxNode.physicsBody?.allowsResting = true

    return boxNode
}

您好,您的 importedBox 是可选的,这意味着它可以有一个值,也可以为零。 您在 importedBox 后面使用“!”(IUO 隐式解包可选),这意味着您告诉编译器您确定它不是 nil。如何在这种情况下它是零因此崩溃 "found nil when unwrapping optional"

所以 recap importedBox 是 nil 但你用 !所以编译器认为它永远不会有 nil 值,但发现 nil 因此崩溃。

要解决此问题,您可以使用保护或可选绑定 守卫例子

func addBox(num: Int) -> SCNNode{

    let boxNode = SCNNode()
    let importedBox = importedSceneBox.rootNode.childNodeWithName("pCube4", recursively: false)
    importedBox?.scale = SCNVector3Make(70, 70, 70)
    guard let unwrapBox = importedBox else { 
     //do your error handling here 
       return SCNNode()
    }
    boxNode.addChildNode(unwrapBox)
    boxNode.position = SCNVector3Make(5, 100, 3)
    let collisionBox = SCNBox(width: 5.0, height: 5.0, length: 5.0, chamferRadius: 0)
    boxNode.physicsBody?.physicsShape = SCNPhysicsShape(geometry: collisionBox, options: nil)
    boxNode.physicsBody = SCNPhysicsBody.dynamicBody()
    boxNode.physicsBody?.mass = 1
    boxNode.physicsBody?.restitution = 0.8
    boxNode.physicsBody?.damping = 0.5
    boxNode.name = "dice" + String(num)
    boxNode.physicsBody?.allowsResting = true

    return boxNode
}

可选绑定示例

func addBox(num: Int) -> SCNNode{

    let boxNode = SCNNode()
    let importedBox = importedSceneBox.rootNode.childNodeWithName("pCube4", recursively: false)
    importedBox?.scale = SCNVector3Make(70, 70, 70)
    if  let unwrapBox = importedBox else { 
        boxNode.addChildNode(unwrapBox)
        boxNode.position = SCNVector3Make(5, 100, 3)
        let collisionBox = SCNBox(width: 5.0, height: 5.0, length: 5.0,     chamferRadius: 0)
        boxNode.physicsBody?.physicsShape = SCNPhysicsShape(geometry: collisionBox, options: nil)
        boxNode.physicsBody = SCNPhysicsBody.dynamicBody()
        boxNode.physicsBody?.mass = 1
        boxNode.physicsBody?.restitution = 0.8
        boxNode.physicsBody?.damping = 0.5
        boxNode.name = "dice" + String(num)
        boxNode.physicsBody?.allowsResting = true

        return boxNode
    }else{
        //do your error handling here 
       return SCNNode()
    }
}

同时作为错误处理案例的旁注,我们正在创建一个默认值,因为您的函数return是一个 SCNNode 而不是可选的 SCNNode。 或者,如果将函数签名更改为

,则可以 return nil
func addBox(num: Int) -> SCNNode? {
     if let unwrappedBox = importedBox {
       //do stuff
     }else{
        return nil 
     }
}