【问题标题】:App stops responding to touches after popping a view controller containing an ARKit scene view弹出包含 ARKit 场景视图的视图控制器后,应用程序停止响应触摸
【发布时间】:2018-11-26 11:57:47
【问题描述】:

我有一个导航控制器,其中包含一个包含单个 UIButton 的根视图控制器。点击按钮将另一个视图控制器推到堆栈上。第二个视图控制器包含一个 ARKit 场景视图 (ARSCNView)。在场景中,我使用 SCNPlane 添加了一个节点,并将平面材质的漫反射内容设置为使用由视图控制器支持的视图,如下所示:

import UIKit
import SceneKit
import ARKit

class SceneViewController: UIViewController {

    @IBOutlet weak var sceneView: ARSCNView!

    override func viewDidLoad() {
        super.viewDidLoad()
        setupScene()
    }

    func setupScene() {
        sceneView.scene = SCNScene()

        let configuration = ARWorldTrackingConfiguration()
        sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])

        // add a small plane at the origin...
        let plane = SCNPlane(width: 0.1, height: 0.1)

        // create a view controller, and add use its view as the plane's material contents...
        let vc = UIViewController()
        vc.view.backgroundColor = UIColor.red
        plane.firstMaterial?.diffuse.contents = vc.view

        let node = SCNNode(geometry: plane)

        sceneView.scene.rootNode.addChildNode(node)
    }
}

当我弹出这个视图控制器(使用后退按钮或平移手势)时,根视图控制器停止响应触摸事件。

将设备旋转到横向,然后再回到纵向似乎确实可以释放导致这种行为的任何因素

我尝试在根视图控制器上覆盖 touchesBegan,但它没有被触发。

我尝试强制窗口成为第一响应者。

我已确保 SceneViewController 正在被销毁,并且在视图控制器被销毁后,sceneView 的会话并未仍在运行。

使用 UIView 或从内容视图控制器的视图生成的 UIImage 时不会出现此问题,但这意味着它无法与之交互。

这是一个示例项目的链接。它需要在支持 ARKit 的设备上运行:https://github.com/duncanlowrie/vc-node-test

【问题讨论】:

    标签: ios swift scenekit arkit


    【解决方案1】:

    我遇到了同样的问题。事实证明,如果您将 SKScene 分配给 plane.firstMaterial?.diffuse.contents,这种行为就会消失,但出于显而易见的原因,您需要 UIView(就像我一样)。

    另外,我认为只有大约三分之二的屏幕变得无响应。我在 iPhone 7 和 iPhone XS 上进行了尝试,如果您尝试与屏幕底部三分之一的内容进行交互,它应该可以工作。丑陋的虫子。

    还尝试使用 Storyboard 中的新入口点重新实例化 AppDelegate 的窗口的 rootViewController:不高兴。

    【讨论】:

    • 我们看到屏幕的一部分对触摸没有响应。
    【解决方案2】:
    /* I think whenever UIView are directly attached to SCNMaterial and    
    that SCNMaterial to SCNNode. SCNMaterial are still being used when  
    previous screen is visited. By resetting ARSCNView seems to resolve the  
    issue. */
    
    import UIKit
    import ARKit
    
    
    class SceneViewController: UIViewController {
    
    @IBOutlet weak var sceneView: ARSCNView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        //do not set setupScene function here 
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewDidLoad()
        //set setupScene function here
        setupScene()
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        //reset ARSCNView before going back to previous screen
        self.sceneView = ARSCNView()
    }
    
    
    func setupScene() {
        sceneView.scene = SCNScene()
    
        let configuration = ARWorldTrackingConfiguration()
        sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
    
        // add a small plane at the origin...
        let plane = SCNPlane(width: 0.1, height: 0.1)
    
        // create a view controller, and add use its view as the plane's    material contents...
        let vc = UIViewController()
        vc.view.backgroundColor = UIColor.red
        plane.firstMaterial?.diffuse.contents = vc.view
    
        let node = SCNNode(geometry: plane)
    
        sceneView.scene.rootNode.addChildNode(node)
    }
    }
    

    【讨论】:

    • 你能补充更多解释吗?
    • @zmag 我认为每当 UIView 直接附加到 SCNMaterial 并将 SCNMaterial 附加到 SCNNode 时。访问前一个屏幕时仍在使用 SCNMaterial。通过重置 ARSCNView 似乎可以解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-08
    • 1970-01-01
    相关资源
    最近更新 更多