Program runs fine in Vision Pro simulator but not on the actual device

I'm trying to figure out how to debug this issue. I have a fairly simple program that I built using the Hello World sample code as reference. Here is my code:

import SwiftUI

@main
struct Core_USDZ_ViewerApp: App {
    
    var body: some Scene {
        
        // Main Menu scene
        //
        WindowGroup (id: "main-menu"){
            CoreUsdzMenu()
        }
        
        // Scene that takes data as an input
        // for volumetric viewing
        //
        WindowGroup (for: URL.self) { $content in
            CoreUsdzVolume(url: content)
        } defaultValue: {
            URL(string: "https://developer.apple.com/augmented-reality/quick-look/models/pancakes/pancakes.usdz")!
        }
        .windowStyle(.volumetric)
        .defaultSize(width: 0.2, height: 0.3, depth: 0.3, in: .meters)
        
        // Full surround scene
        /*
        ImmersiveSpace {
            // put our immersive view here
        } */
    }
}

In the simulator, this launches the main menu scene, but when installed on the Vision Pro using TestFlight it skips the main menu and goes straight to the second WindowGroup. Since the data isn't populated, it uses the defaultValue and just shows pancakes.

I'm having trouble logging and debugging this issue, as I don't have access to the hardware myself. I have to push the code to TestFlight and wait for a coworker to test it.

Does anyone have ideas of why this could be happening? Any help is appreciated. Logging and debugging tips especially. I'm used to just putting log messages in my code to debug, but maybe there are some breakpoint techniques I should be using here or something.

Oh, also, here is my CoreUsdzMenu script:

import SwiftUI
import RealityKit
import UniformTypeIdentifiers

struct CoreUsdzMenu: View {
    @Environment(\.openWindow) private var openWindow
    @Environment(\.dismissWindow) private var dismissWindow
    
    @State var entity: Entity? = nil
    @State var showFilePicker: Bool = false
    
    init() {
        NSLog("In CoreUsdzMenu")
    }
    
    var body: some View {
        VStack{
            Text("Core USDZ Viewer v1.1")
                .font(.title)
                .frame(width: 500.0, height: 100.0)
            
            /* usdz list
            HStack(spacing: 100.0) {
                Spacer()
                // Load the UsdzList view into the window!
                UsdzList()
                
                Spacer()
            }*/
            
            /* button test for window
            Button {
                openWindow(value: usdzData[1].url)
            } label: {
                Text("open test window")
            }*/
            
            // A view for displaying the loaded asset.
            /*
            RealityView(
                make: { content in
                    // Add a placeholder entity to parent the entity to.
                    //
                    let placeholderEntity = Entity()
                    placeholderEntity.name = "$__placeholder"
                    
                    if let loadedEntity = self.entity {
                        placeholderEntity.addChild(loadedEntity)
                    }
                    
                    content.add(placeholderEntity)
                },
                update: { content in
                    guard let placeholderEntity = content.entities.first(where: {
                        $0.name == "$__placeholder"
                    }) else {
                        preconditionFailure("Unable to find placeholder entity")
                    }
                    
                    // If there is a loaded entity, remove the old child,
                    // and add the new one.
                    //
                    if let loadedEntity = self.entity {
                        placeholderEntity.children.removeAll()
                        placeholderEntity.addChild(loadedEntity)
                    }
                }
            )*/
            
            // A button that displays a file picker for loading a USDZ.
            //
            Button(
                action: {
                    showFilePicker = true
                },
                label: {
                    Text("Load USDZ")
                }
            )
                .padding()
        }
        // can import usdz and realityFile UTT types
        .fileImporter(isPresented: $showFilePicker, allowedContentTypes: [.usdz, .realityFile]) { result in
            // Get the URL of the USDZ picked by the user.
            // Guarded for errors.
            //
            guard let url = try? result.get() else {
                print("Unable to get URL")
                return
            }
            
            NSLog("In CoreUsdzMenu")
            
            // add new .usdz to our data list
            // for later!~
            // use Observables n stuff
            //usdzData.addUsdz(url)
            
            // This task is just an asynchronous block of code. Not linked
            // to the RealityView explicitly; the update parameter of the
            // RealityView function responds when this task updates the entity.
            //
            Task {
                // As the app is sandboxed, permission needs to be
                // requested to access the file, as it's outside of
                // the sandbox.
                //
                if url.startAccessingSecurityScopedResource() {
                    defer {
                        url.stopAccessingSecurityScopedResource()
                    }
                    
                    // Load the USDZ asynchronously.
                    // On load, triggers RealityView's update.
                    //
                    //self.entity = try await Entity(contentsOf: url)
                    
                    // Try using the Volumetric Window to display the
                    // content:
                    //
                    openWindow(value: url)
                }
            }
        }
    }
}

Thank you for reading!

Replies

Please double check your Info.plist. VisionOS will launch the first WindowGroup that matches the Preferred Default Scene Session Role aka UIApplicationPreferredDefaultSceneSessionRole in your Info.plist. Setting it to UIWindowSceneSessionRoleApplication will cause it initially open the first non volumetric window (main-menu) and setting it to UIWindowSceneSessionRoleVolumetricApplication will cause it to initially open the first volumetric (.windowStyle(.volumetric)) window (the one containing CoreUsdzVolume).

  • My info.plist only has icon file, allow multiple windows, and app uses non-exempt encryption defined. At one point earlier in the project I did have that variable defined, but I deleted it. I will try setting it explicitly and see if that helps

Add a Comment