I am building a simple SwiftUI Augmented Reality app that allows to display a 3D model from a list of models.
ScrollView {
LazyVGrid(columns: Array(repeating: item, count: 3), spacing: 3) {
ForEach(items, id: \.self) { item in
ZStack {
NavigationLink(destination: ItemDetailsView(item: item)) ) {
ListItemCell(item: item,
itemUUID: "\(item.uuid)",
imageURL: item.imageURL)
}
}
.aspectRatio(contentMode: .fill)
}
}
}
.navigationTitle("\(list.listName)")
When I tap on a ListItemCell, I load a UIViewRepresentable to display the AR model.
func makeUIView(context: Context) -> ARView {
// Create arView for VR with background color
let arView = ARView(frame: .zero, cameraMode: .nonAR, automaticallyConfigureSession: false)
arView.environment.background = .color(UIConfiguration.realityKit3DpreviewBackgroundColor)
// Set world anchor
let worldAnchor = AnchorEntity(world: .zero)
arView.scene.addAnchor(worldAnchor)
// Load 3D model
loadAsset(at: worldAnchor, context: context)
// Setup camera
setupCamera(on: worldAnchor)
// Add spot lights
setupLighting(on: worldAnchor)
// Install gestures for 3D model
setupGesturesForARView(arView, context: context)
// Add camera to coordinator for interactions
context.coordinator.perspectiveCamera = preview3DViewModel.perspectiveCamera
return arView
}
Load Asset:
private func loadAsset(at worldAnchor: AnchorEntity, context: Context) {
var cancellable: AnyCancellable? = nil
cancellable = Entity.loadAsync(named: "item")
.sink(receiveCompletion: { completion in
if case let .failure(error) = completion {
print("Unable to load model: \(error)")
}
cancellable?.cancel()
}) { model in
if let item = model.findEntity(named: "rootModel") as? ItemEntity {
//... do stuff
// Add item to ARView
worldAnchor.addChild(item)
}
cancellable?.cancel()
}
}
Everything works fine but I have a memory leak issue. When I profile the app or check the debug memory graph, everytime I load an asset using the Entity.loadAsync method, it leaks a series of blocks as per the screenshot.
The memory footprint grows as I load more models. Whether I load models in real AR or non-AR, it leaks. In AR it eventually crashes when there are too many models and throws an EXC_BAD_ACCESS error on the @main function.
I have tried the following to no effect:
- loading a simple Apple provided .reality model instead of mine (to check if something was wrong with mine)
- loading from a function in the coordinator
- loading from a function in a viewModel as an ObservedObject
- loading during the UIViewRepresentable init
- loading during the onAppear {} event in the SwiftUI view
Could you help?
Thanks