Cannot pause and deallocate ARSession using SwiftUI and ARKit

Hi,

I'm developing an AR App using Apple ARKit. At the moment in my AugmentedView I'm using the boilerplate directly provided by Apple for AR Apps template when choosing initial type of project.

When I run my app in debug mode I see that I'm receiving this warning/advice in the console:

ARSession is being deallocated without being paused. Please pause running sessions explicitly.

Is possible to pause ARSession in SwiftUI? Because as far as I know all this stuff is managed by default by the OS. Is that correct?

To notice, I have two Views, a parent View and by using a NavigationStack / NavigationLink the child "subView"

Here is my code snippet for the parent View:

import SwiftUI

struct ArIntroView: View {

    var body: some View {
        
        NavigationStack{
            NavigationLink(destination: AugmentedView(), label: {
                HStack {
                    Text("Go to ARView")
                }
                .padding()
            }
          )
        } 
    }
}

struct ArIntroView_Previews: PreviewProvider {
    static var previews: some View {
        ArIntroView()
    }
}

Here is my code for the child View:

import SwiftUI
import RealityKit

struct AugmentedView : View {
    
    @State private var showingSheet = false
    
    // add state to try explicitly end AR
    // @State private var isExitTriggered: Bool = false

    var body: some View {
        
        ZStack {
            ARViewContainer()
            // to hide toolbar in View
            .toolbar(.hidden, for: .tabBar)
            .ignoresSafeArea(.all)
            
            VStack {
                Spacer()
                HStack {
                    Button {
                        //toggle bottom sheet
                        showingSheet.toggle()
                    } label: {
                        Text("Menu")
                            .frame(maxWidth: .infinity)
                            .padding()
                    }
                    .background()
                    .foregroundColor(.black)
                    .cornerRadius(10)
                    
                    //present the bottom sheet
                    .sheet(isPresented: $showingSheet) {
                        HStack{
                            Button {
                                // dismiss bottom sheet
                                showingSheet.toggle()
                            } label: {
                                Label("Exit", systemImage: "cross")
                            }
                        }
                        .presentationDetents([.medium])
                        .presentationDragIndicator(.visible)
                        
                    }
                }
                .padding()
            }
            Spacer()
        } 
    }   
}


struct ARViewContainer: UIViewRepresentable {
    
    // @Binding var isExitTriggered: Bool
    
    let arView = ARView(frame: .zero)
    
    func makeUIView(context: Context) -> ARView {
        
        
        // Load the "Box" scene from the "Experience" Reality File
        let boxAnchor = try! Experience.loadBox()
        
        // Add the box anchor to the scene
        arView.scene.anchors.append(boxAnchor)
        
        return arView
        
    }
      
    // not work it will remove the View and after it will re-create it from makeUIView
    func updateUIView(_ uiView: ARView, context: Context) {
        // if isExitTriggered {
        //    uiView.session.pause()
        //   uiView.removeFromSuperview()
        // }
    }
    
}

#if DEBUG
struct Augmented_Previews : PreviewProvider {
    static var previews: some View {
        AugmentedView()
    }
}
#endif

In addition, when running the app and check the performance with Apple Instruments, during the AR session I have memory leaks, apparently with the CoreRE library here the snap:

Any suggestion or critique will be welcome.

Answered by jackInTheNet in 758620022

Hi,

I've found the solution. Practically I cannot use subViews or NavLink with an AR Environment inside, and that make sense. That's because if I start an AR session and then press the "back" button basically the session runs on the parent view not in the subView, so going back from child to parent doesn't stop the AR Session which is running in the parent view.

The solution was quite simple, I've added a custom back button, and @Environment(.dismiss) to trigger in a fund updateUIView, so if triggered it will dismiss the scene and stop the AR Session.

Accepted Answer

Hi,

I've found the solution. Practically I cannot use subViews or NavLink with an AR Environment inside, and that make sense. That's because if I start an AR session and then press the "back" button basically the session runs on the parent view not in the subView, so going back from child to parent doesn't stop the AR Session which is running in the parent view.

The solution was quite simple, I've added a custom back button, and @Environment(.dismiss) to trigger in a fund updateUIView, so if triggered it will dismiss the scene and stop the AR Session.

Just implement the function on your UIViewRepresentable struct like this:

    static func dismantleUIView(_ uiView: ARView, coordinator: ()) {
        uiView.session.pause()
    }
Cannot pause and deallocate ARSession using SwiftUI and ARKit
 
 
Q