2

I am running an ARKit Session where I place SceneKit nodes. With every node I am instantiating a new view controller and pass its view as the node's content like so:

func createTextNode(anchor: ARCardAnchor) -> SCNNode? {
    let plane = SCNPlane()
    plane.height = 0.5
    plane.width = 0.5

    let sb = UIStoryboard(name: "Main", bundle: nil)
    let fCVC = sb.instantiateViewController(withIdentifier: "CardViewController") as! CardViewController


    plane.firstMaterial?.diffuse.contents = fCVC.view
    let cardNode = SCNNode(geometry: plane)
    cardNode.constraints = [billboardConstraint]
    return cardNode
}

I am adding the nodes to the scene using the following ARSCNViewDelegate method and my custom ARCardAnchor (a subclass of ARAnchor):

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    if let fcanchor = anchor as? ARCardAnchor {
        DispatchQueue.main.async {
            guard let n = self.nodeCreator.createTextNode(anchor: fcanchor) else { return }
            node.addChildNode(n)

        }
    }
}

So far everything works and the nodes are placed in 3D space. But when I navigate back to the previous View Controller the UI freezes and I can't do anything. I've tried using an unwind segue like this

@IBAction func goBackToPrevious(_ sender: Any) {
    sceneView.session.pause()
    self.performSegue(withIdentifier: "unwindToPrevious", sender: self)
}

and a navigation controller where I pop the AR scene controller off the stack. Every time the previous view controllers are frozen. No errors in Xcode, the app keeps running . If I wait for approx. 2 minutes I can use the screen again. If I don't add nodes with view controllers to my AR scene, everything works perfectly fine. My only explanation is that the UIThread is overwhelmed when adding nodes because it creates a massive memory leak somewhere (that I haven't found despite of 10 hours of debugging). Has anyone had a similar experience and can tell me how to resolve this? What can I do to debug this and ensure smooth navigation?

Sebastian
  • 445
  • 5
  • 20
  • Have you tried using Instruments? Allocations/Leaks would be helpful here. – Tomasz Pe Feb 03 '19 at 22:13
  • Yeah, I used the main thread checker as well as Malloc Stack logging. I'm just seeing that the main thread checker tells me that I am calling the UI from a background thread. This occurs with all other ARKit apps as well and doesn't lead to the same issue. So it seems this is an issue on Apple's side. – Sebastian Feb 04 '19 at 07:46

2 Answers2

1

The problem was that I assigned my custom UIViewController views directly to the nodes' planes. My assumption is that this created reference cycles since the view controllers held references to objects that I used elsewhere in the scene. I resolved it by capturing an image of the view and assigning that one to the node. Seems like it is generally a dangerous practice to assign UIViews directly to nodes because it invites reference cycles. Maybe someone more qualified on memory issues and/or SceneKit can give an opinion on this.

Sebastian
  • 445
  • 5
  • 20
0
 /* 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. */

 //try this 
 override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    //reset ARSCNView before going back to previous screen
    self.sceneView = ARSCNView()
 }