Swift ARKit SceneView nil при добавлении 3D-объекта из другого контроллера просмотра

В моей раскадровке у меня есть 2 простых viewController. Представление, которое отображается при запуске приложения с простой компоновкой, содержащей кнопку. При нажатии на кнопку переходите, показывая второй viewController, в котором находится ARSCNView.

    @IBOutlet weak var sceneView: ARSCNView!

В viewDidLoad я могу добавить 3D-объект, также есть touchBegin, чтобы показать дополнительный 3D-объект при нажатии на плоскость. Прекрасно работает.

Однако мой первый viewController должен инициировать добавление 3D-объекта на сцену при определенном делегате, который происходит в моем первом viewController. Первый viewController просто вызывает функцию на моем втором viewController для добавления 3D-объекта (та же функция, которую я использую для добавления 3D-объекта при нажатии на плоскость).

    secondViewController.add3DObject()

Когда он вызывает add3DObject из моего первого viewController, sceneView равен нулю.

Когда я могу добавить 3D-объект, который запускается вторым viewController, почему я не могу запускать одно и то же с помощью другого 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)
    }

}

Не могли бы вы опубликовать здесь более подробный код, чтобы нам было легче помочь вам определить проблему?

HSG 24.06.2019 08:20

Добавлен пример кода выше. Надеюсь, это имеет смысл.

user19100 24.06.2019 20:09

В контроллере первого представления var arSceneViewController = ARSceneViewController() //second viewController Я думаю, здесь вы должны инициализировать контроллер второго представления из раскадровки?

HSG 24.06.2019 23:40

Спасибо за ваше предложение... Я новичок в Swift. Не могли бы вы уточнить, как я буду это делать, пожалуйста?

user19100 25.06.2019 04:02

Хорошо, я опубликую код в качестве своего ответа, вы можете попробовать и сообщить мне, работает ли он.

HSG 25.06.2019 05:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
232
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Как уже говорилось, я надеюсь, что этот код работает для вас.

При нажатии на кнопку переходите, показывая второй viewController, в котором находится ARSCNView. --> Таким образом, мы получим второй контроллер представления, переопределив функцию подготовки к переходу (пожалуйста, замените «ваш идентификатор перехода для второго контроллера представления» фактическим идентификатором, который вы установили в раскадровке).

А в делегате 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)
    }
}

Большое вам спасибо за вашу помощь!! Это сработало. Требуется ли всегда готовиться к переходу? У меня это было только в раскадровке.

user19100 26.06.2019 03:48

Рад, что это помогает вам. На самом деле это зависит от того, как вы настроите свою раскадровку. Если вы настроите переход для отправки на новый контроллер представления, вам придется переопределить этот метод, чтобы получить целевой контроллер представления. В противном случае, если вы активируете ручное нажатие/представление, вы инициируете второй контроллер представления из раскадровки и сохраняете ссылку на него для использования.

HSG 26.06.2019 06:00

Другие вопросы по теме