从其他viewcontroller添加3D对象时,Swift ARKit SceneView无效

时间:2019-06-24 02:53:50

标签: ios swift augmented-reality

在情节提要中,我有2个简单的viewController。在应用程序启动时显示的视图,布局简单,包含一个按钮。单击按钮时,通过显示包含ARSCNView的第二个viewController进行选择。

    @IBOutlet weak var sceneView: ARSCNView!

在viewDidLoad中,我可以添加3D对象,也可以使用touchBegin在平面上点击时显示其他3D对象。效果很好。

但是,当我的第一个viewController中发生某些委托时,我的第一个viewController需要触发将3D对象添加到场景中。第一个viewController只需在第二个viewController上调用一个函数即可添加3D对象(与我在平面上点击时用于添加3D对象的函数相同)。

    secondViewController.add3DObject()

当它从我的第一个viewController调用add3DObject时,sceneView为nil。

当我能够添加由第二个viewController触发的3D对象时,为什么不能通过不同的viewController触发同一件事?

第一个viewController :(省略与问题无关的全部代码)

    class ViewController: UIViewController, CLLocationManagerDelegate {

       var locationManager = CLLocationManager()
       var arSceneViewController = ARSceneViewController() //second viewController

        func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
         // omitting some logic here....
         // call a function in second view controller
         arSceneViewController.addARItems(item: item)
        }
    }

第二个viewController :(省略了与问题无关的全部代码)

    class ARSceneViewController: UIViewController, ARSCNViewDelegate {

        @IBOutlet weak var sceneView: ARSCNView!

         // this works 
         override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
             if let touch = touches.first{
             let touchLocation = touch.location(in: sceneView)

             let results = sceneView.hitTest(touchLocation, types: .existingPlaneUsingExtent)
             var arItem = ARItem()
             arItem.itemDescription = "hello"
            if let hitResult = results.first{
                // calling this works from here
                addARItems(item: arItem ,atLocation: hitResult)
            }
        }
      }

    // Called from first ViewController doesn't work
    // Called from the same file work (from touchesBegin)
    func addARItems(item: ARItem, atLocation location:ARHitTestResult? = nil){
        // sceneView is nil!!!
        guard let sView =  sceneView else { return }       

        // omitted some insignificant code here ...

        let cube = SCNBox(width:0.5, height: 0.1, length: 0.1, chamferRadius: 0.01)
        let node = SCNNode()
        node.position = SCNVector3(0, 0.1, -0.5)
        node.geometry = cube

        sceneView.scene.rootNode.addChildNode(node)
    }

}

1 个答案:

答案 0 :(得分:0)

如前所述,我希望这段代码对您有用。

单击按钮时,通过显示包含ARSCNView的第二个viewController进行查找。 ->因此,我们将通过覆盖功能来为segue做准备来获取第二个视图控制器(请用您在情节提要中设置的实际标识符替换“您的第二个视图控制器的segue ID”)。

然后在委托locationManager didUpdateHeading中,我们将检查第二个视图控制器是否存在,然后调用addARItems

var arSceneViewController: ARSceneViewController? //second viewController

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "your segue id for second view controller" {
        arSceneViewController = segue.destination as? ARSceneViewController
    }
}

func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
    // omitting some logic here....
    // call a function in second view controller
    if let arSceneVC = arSceneViewController {
         arSceneVC.addARItems(item: item)
    }
}