Background: This is a simple visionOS empty application. After the app launches, the user can enter an ImmersiveSpace by clicking a button. Another button loads a 33.9 MB USDZ model, and a final button exits the ImmersiveSpace.
Below is the memory usage scenario for this application:
- After the app initializes, the memory usage is 56.8 MB.
- After entering the empty ImmersiveSpace, the memory usage increases to 64.1 MB.
- After loading a 33.9 MB USDZ model, the memory usage reaches 92.2 MB.
- After exiting the ImmersiveSpace, the memory usage slightly decreases to 90.4 MB.
Question: While using a memory analysis tool, I noticed that the model's resources are not released after exiting the ImmersiveSpace. How should I address this issue?
struct EmptDemoApp: App {
@State private var appModel = AppModel()
var body: some Scene {
WindowGroup {
ContentView()
.environment(appModel)
}
ImmersiveSpace(id: appModel.immersiveSpaceID) {
ImmersiveView()
.environment(appModel)
.onAppear {
appModel.immersiveSpaceState = .open
}
.onDisappear {
appModel.immersiveSpaceState = .closed
}
}
.immersionStyle(selection: .constant(.mixed), in: .mixed)
}
}
struct ContentView: View {
@Environment(AppModel.self) private var appVM
var body: some View {
HStack {
VStack {
ToggleImmersiveSpaceButton()
}
if appVM.immersiveSpaceState == .open {
Button {
Task {
if let url = Bundle.main.url(forResource: "Robot", withExtension: "usdz") {
if let model = try? await ModelEntity(contentsOf: url, withName: "Robot") {
model.setPosition(.init(x: .random(in: 0...1.0), y: .random(in: 1.0...1.6), z: -1), relativeTo: nil)
appVM.root?.add(model)
print("Robot: \(Unmanaged.passUnretained(model).toOpaque())")
}
}
}
} label: {
Text("Add A Robot")
}
}
}
.padding()
}
}
struct ImmersiveView: View {
@Environment(AppModel.self) private var appVM
var body: some View {
RealityView { content in
appVM.root = content
}
}
}
struct ToggleImmersiveSpaceButton: View {
@Environment(AppModel.self) private var appModel
@Environment(\.dismissImmersiveSpace) private var dismissImmersiveSpace
@Environment(\.openImmersiveSpace) private var openImmersiveSpace
var body: some View {
Button {
Task { @MainActor in
switch appModel.immersiveSpaceState {
case .open:
appModel.immersiveSpaceState = .inTransition
appModel.root = nil
await dismissImmersiveSpace()
case .closed:
appModel.immersiveSpaceState = .inTransition
switch await openImmersiveSpace(id: appModel.immersiveSpaceID) {
case .opened:
break
case .userCancelled, .error:
fallthrough
@unknown default:
appModel.immersiveSpaceState = .closed
}
case .inTransition:
break
}
}
} label: {
Text(appModel.immersiveSpaceState == .open ? "Hide Immersive Space" : "Show Immersive Space")
}
.disabled(appModel.immersiveSpaceState == .inTransition)
.animation(.none, value: 0)
.fontWeight(.semibold)
}
}