在情节提要中,我有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)
}
}
答案 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)
}
}