1

I am trying to integrate an ARKit view which processes frames with machine learning and shows the results on the screen. I have gotten the ARKit view to work with UIViewRepresentable and everything works until a state changes. How do I make the AR view static and not update when a state changes. I only want to update the label that shows the result.

This is the error that I receive when the state changes: [CAMetalLayer nextDrawable] returning nil because allocation failed.

This presumably happens because the arView is being constantly reloaded as it processes the frames? Not too sure though.

This is the code for the view:

struct ARControlView: View {
    @EnvironmentObject var resultHandler: ResultHandler
    var body: some View {
        let arView = ARViewContainer() // This is the UIViewRepresentable containing the ARKit view.
        return ZStack {
            arView
            VStack {
                Text(self.resultHandler.gesture.rawValue)
            }
            .onAppear {
                arView.restartARSession()
            }
            .onDisappear {
                arView.pauseArSession()
            }
        }
    }
}

This is for the ARViewContainer:

struct ARViewContainer: UIViewRepresentable {

    var arView = ARView(frame: .zero)
    @EnvironmentObject var resultHandler: ResultHandler

    func makeUIView(context: Context) -> ARView {
        arView.session.delegate = context.coordinator
        arView.session.run(AROrientationTrackingConfiguration())
        return arView
    }

    func pauseArSession() {
        arView.session.pause()
    }

    func restartARSession() {
        arView.session.run(AROrientationTrackingConfiguration())
    }

    func updateUIView(_ uiView: ARView, context: Context) {}

    class Coordinator: NSObject, ARSessionDelegate {
        // Process frames here...
    }

    func makeCoordinator() -> ARViewContainer.Coordinator {
        Coordinator(self)
    }
}
Privitec
  • 69
  • 6
  • 1
    just put the variable which causes the state change in another environmentobject which you do not use in your arviewViewcontainer – Chris Mar 14 '20 at 08:48
  • I have tried many ways of giving the result to the ARControlView but none work without the error. I have even tried something as simple as a button that changes a test @State that is just a basic string and the error happens. This is why I have come to the conclusion that it is happening because the View is re-rendering the ARContainerView while it is still using the camera or completing tasks. – Privitec Mar 14 '20 at 08:54

2 Answers2

1

Every time there is a state change in resultHandler, body is re-evaluated in ARControlView.

This causes a new ARViewContainer to be instantiated due to let arView = ARViewContainer() being inside the body variable.

If you move let arView = ARViewContainer() outside of the body variable, arView won't be reinstantiated every time there is a state change.

Vlad
  • 932
  • 6
  • 18
1

I found out that the issue actually wasn't as it seemed. The error I was receiving was due to the frame being set to .zero which for some reason made it return nil. Also set it to not automatically configure because that also created weird issue causing the image to be stretched.

This was the line that I changed:

From:

var arView = ARView(frame: .zero)

To:

var arView = ARView(frame: .init(x: 1, y: 1, width: 1, height: 1), cameraMode: .ar, automaticallyConfigureSession: false)

Thanks for anyones else's help I appreciate it!

Privitec
  • 69
  • 6