Cannot reassign worldTracking / planeDetection providers in my PlacementManager when switching environments

Cannot reassign worldTracking / planeDetection providers in my PlacementManager when switching environments

Environment

  • Xcode: 15.x (15Bxx)
  • VisionOS SDK 1.x / iOS 17
  • Swift 5.9
  • Targets: Apple Vision Pro (immersive space)
  • Frameworks: ARKit, RealityKit, SwiftUI

What I’m Trying to Do
I have a view-model class PlacementManager that holds two AR providers:

private var worldTracking: WorldTrackingProvider
private var planeDetection: PlaneDetectionProvider

I want to dynamically replace these providers in a setEnvironment(_:) method (so I can save/clear a JSON scene and restart ARKit).

What’s Happening

  1. If I declare them as :
private let worldTracking = WorldTrackingProvider()
private let planeDetection = PlaneDetectionProvider()

I get compile-errors when I later do:

self.worldTracking = newWorldTracking // Cannot assign to property: 'worldTracking' is a 'let' constant

2" If I change them to un-initialized vars:

private var worldTracking: WorldTrackingProvider
private var planeDetection: PlaneDetectionProvider

then in my init() I get:

self used in property access 'worldTracking' before all stored properties are initialized

Code Snippet

@Observable
final class PlacementManager : ObservableObject {
    private var worldTracking: WorldTrackingProvider
    private var planeDetection: PlaneDetectionProvider
    // … other props …
  
    @MainActor
    init() {
        // error: self.worldTracking used before init…
        planeAnchorHandler = PlaneAnchorHandler(rootEntity: root)
        persistenceManager = PersistenceManager(
          worldTracking: worldTracking,
          rootEntity: root
        )
        // …
    }

    @MainActor
    func setEnvironment(env: Environnement) async {
        let newWorldTracking  = WorldTrackingProvider()
        let newPlaneDetection = PlaneDetectionProvider()
        try await appState!.arkitSession.run(
          [ newWorldTracking, newPlaneDetection ]
        )
        self.worldTracking  = newWorldTracking
        self.planeDetection = newPlaneDetection
        // …
    }
}

What I’ve Tried

  • Giving them default values at declaration (= WorldTrackingProvider())
  • Initializing them at the top of init() before any use
  • Passing the new providers into arkitSession.run(...)

My Question
What is the recommended Swift-style pattern to declare and reassign these ARKit provider properties so that:

  1. They’re fully initialized before use in init(), and
  2. I can swap them out later in setEnvironment(...) without compiler errors?

Any pointers (or links to forum threads / docs) would be greatly appreciated!

Without knowing more about exactly how you're initializing these properties, you could initialize your values as local variables first and assign them as properties later, which should prevent the compilation error you're getting:

@MainActor
init() {
    let worldTracking = WorldTrackingProvider()

    persistenceManager = PersistenceManager(
      worldTracking: worldTracking,
      // ...
    )
    
    self.worldTracking = worldTracking
}