Swift 当从不同 viewcontroller 添加 3D 对象时,ARKit SceneView 为零
Swift ARKit SceneView nil when adding 3D object from different viewcontroller
在我的故事板中,我有 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 为零。
当我能够添加由第二个 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)
}
}
如前所述,我希望这段代码对你有用。
单击一个按钮时,通过显示第二个 viewController 来继续,其中包含 ARSCNView。 --> 因此我们将通过覆盖 func prepare for segue 来获得第二个视图控制器(请将 "your segue id for second view controller" 替换为您在故事板中设置的实际标识符)。
并且在委托 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)
}
}
在我的故事板中,我有 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 为零。
当我能够添加由第二个 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)
}
}
如前所述,我希望这段代码对你有用。
单击一个按钮时,通过显示第二个 viewController 来继续,其中包含 ARSCNView。 --> 因此我们将通过覆盖 func prepare for segue 来获得第二个视图控制器(请将 "your segue id for second view controller" 替换为您在故事板中设置的实际标识符)。
并且在委托 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)
}
}