在我的 Storyboard中,我有 2 个简单的 viewController。在应用程序启动时显示的 View ,具有简单的布局,其中包含一个按钮。单击按钮时,通过显示包含 ARSCNView 的第二个 viewController 来继续。
@IBOutlet weak var sceneView: ARSCNView!
在 viewDidLoad 中,我可以添加 3D 对象,还可以使用 touchBegin 在平面上点击时显示其他 3D 对象。效果很好。
但是,我的第一个 viewController 需要根据第一个 viewController 中发生的某些委托(delegate)触发将 3D 对象添加到场景中。第一个 viewController 只是调用第二个 viewController 上的函数来添加 3D 对象(与我在平面上点击时添加 3D 对象的函数相同)。
secondViewController.add3DObject()
当它从我的第一个 viewController 调用 add3DObject 时,sceneView 为零。
当我能够添加由第二个 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)
}
}
最佳答案
正如所讨论的,我希望这段代码适合您。
当单击按钮时,通过显示包含 ARSCNView 的第二个 viewController 来继续。 --> 因此,我们将通过覆盖 func prep for segue 来获取第二个 View Controller (请将“第二个 View Controller 的第二个 View Controller 的 segue id”替换为您在 Storyboard中设置的实际标识符)。
在委托(delegate) locationManager didUpdateHeading 中,我们将检查第二个 View Controller 是否存在,然后调用 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)
}
}
关于ios - 从不同 View Controller 添加 3D 对象时,Swift ARKit SceneView nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56729333/