Bug: When SpatialTrackingSession and ARKitSession + WorldTrackingProvider are running concurrently, any WorldAnchor added via WorldTrackingProvider.addAnchor() triggers .added followed immediately by .removed—without any user call to removeAnchor(). The anchor never persists in allAnchors.
import SwiftUI
import RealityKit
import ARKit
struct ImmersiveView: View {
@State private var worldTracking: WorldTrackingProvider?
@State private var arSession: ARKitSession?
@State private var processWorldTrackingUpdatesTask: Task<Void, Never>?
var body: some View {
RealityView { content in
let configuration = SpatialTrackingSession.Configuration(tracking: [.world])
if let unavailableCapabilities = await SpatialTrackingSession().run(configuration) {
if unavailableCapabilities.anchor.contains(.world) {
fatalError("World tracking is not available on this device.")
}
}
let worldTracking = WorldTrackingProvider()
let arSession = ARKitSession()
self.arSession = arSession
try! await arSession.run([worldTracking])
self.worldTracking = worldTracking
processWorldTrackingUpdatesTask = Task { @MainActor [weak worldTracking] in
guard let worldTracking else { return }
for await update in worldTracking.anchorUpdates {
let worldAnchor = update.anchor
switch update.event {
case .added:
print("Anchor added: \(worldAnchor.id)")
case .updated:
print("Anchor updated: \(worldAnchor.id)")
case .removed:
fatalError("Anchor removed unexpectedly — this should not happen in this demo scenario.")
}
}
}
}
.task {
try? await Task.sleep(for: .seconds(3))
guard let worldTracking else { return }
do {
try await worldTracking.addAnchor(.init(originFromAnchorTransform: Transform.identity.matrix))
} catch {
print("Error adding anchor: \(error)")
}
}
}
}
Expected: Anchors persist until explicitly removed or out of range.
Actual: SpatialTrackingSession interferes with WorldTrackingProvider's anchor lifecycle, causing immediate removal.
This was originally reported in 2025 (https://developer.apple.com/forums/thread/773351) , but remains unfixed in visionOS 27.0 beta. I've re-filed as FB23420195.
I was wishing for an ARKit engineer to jump into this thread as I have not used that framework is a very long time. However I think you are answering your question as I don’t think those were ever intended to be used simultaneously for world tracking. Based on every sample and documentation I have seen.
If your app requires persistent world anchors, my suggestion is to completely drop SpatialTrackingSession and exclusively use ARKitSession with a WorldTrackingProvider.
If you were using SpatialTrackingSession for other things, you should migrate those to the ARKitSession as well by adding a any other provider?
Choose ARKitSession when you need persistence, when you call worldTracking.addAnchor(newAnchor). The system remembers this anchor on subsequent app launches in the same physical space.
I think you should describe to the ARKit engineers what you are trying to accomplish and maybe we can find a sample that will help you at least start on that path?
Albert WWDR