Search code examples
swiftipadaugmented-realityarkitswift-playground

iPad Swift Playgrounds won’t run ARKit code/crashes


I’ve been experimenting with ARKit on Swift Playgrounds. I’ve written the starter code, but when I run it nothing happens. Instead of evaluating the code, it displays the pop up that shows ay issues in the code. Error in code

I know the code I’m using works, because I’ve used the same code on an iPad running an older version of Swift Playgrounds and the code works perfectly. It seems to be a problem with either Swift Playgrounds 3 or Swift 5.

Here’s the interesting part. When I remove the line of code that runs the ARWorldTrackingConfiguration initializer, and the code that makes the view controller the delegate of the session and scene, the code runs just fine. When I put it back, it does the same error again. I don’t know what’s going wrong.

I’m running Swift Playgrounds 3.0 on and iPad 6th Generation. The playground uses ARKit, UIKit, SceneKit, and PlaygroundSupport.

Lastly, here’s some code.

// Code inside modules can be shared between pages and other source files.
import ARKit
import SceneKit
import UIKit
extension ARSCNView {
    public func setup(){
        antialiasingMode = .multisampling4X
        automaticallyUpdatesLighting = false
        preferredFramesPerSecond = 60
        contentScaleFactor = 1.0
        if let camera = pointOfView?.camera {
            camera.wantsHDR = true
            camera.wantsExposureAdaptation = true
            camera.exposureOffset = -1
            camera.minimumExposure = -1
            camera.maximumExposure = 3
        }
    }
}
public class vc : UIViewController, ARSessionDelegate, ARSCNViewDelegate {
    var arscn : ARSCNView!
    var scene : SCNScene!
    public override func loadView() {
        arscn = ARSCNView(frame: CGRect(x: 0, y: 0, width: 768, height: 1024))
        arscn.delegate = self
        arscn.setup()
        scene = SCNScene()
        arscn.scene = scene
        var config = ARWorldTrackingConfiguration()
        config.planeDetection = .horizontal
        arscn.session.delegate = self
        self.view = arscn
        arscn.session.run(configåå)
    }
    public func session(_ session: ARSession, didFailWithError error: Error) {
        // Present an error message to the user
    }

    public func sessionWasInterrupted(_ session: ARSession) {
        // Inform the user that the session has been interrupted, for example, by presenting an overlay
    }

    public func sessionInterruptionEnded(_ session: ARSession) {
        // Reset tracking and/or remove existing anchors if consistent tracking is required
    }
}

Lastly, please note that I’m presenting the live view in the main playground page and putting the class in the shared code.


Solution

  • I’ve figured out a way to make this work. All I had to do was assign the view controller to a variable and then present the variable. I’m not exactly sure why this works, I just know it does.

    import ARKit
    import SceneKit
    import UIKit
    import PlaygroundSupport
    
    public class LiveVC: UIViewController, ARSessionDelegate, ARSCNViewDelegate {
    
        let scene = SCNScene()
        public var arscn = ARSCNView(frame: CGRect(x: 0,y: 0,width: 640,height: 360))
    
        override public func viewDidLoad() {
            super.viewDidLoad()
            arscn.delegate = self
            arscn.session.delegate = self
            arscn.scene = scene
            let config = ARWorldTrackingConfiguration()
            config.planeDetection = [.horizontal]
            arscn.session.run(config)
            view.addSubview(arscn)
        }
        public func session(_ session: ARSession, didFailWithError error: Error) {}
        public func sessionWasInterrupted(_ session: ARSession) {}
        public func sessionInterruptionEnded(_ session: ARSession) {}
    }
    var vc = LiveVC()
    PlaygroundPage.current.liveView = vc
    PlaygroundPage.current.needsIndefiniteExecution = true