Reading scenePhase from custom Scene

Hi, I've encountered a thread where an Apple engineer points out that there are 2 possible ways to anchor scenePhase, either App or View implementation: https://developer.apple.com/forums/thread/757429

This thread also links to documentation which states

If you read the phase from within a custom Scene instance, the value similarly reflects an aggregation of all the scenes that make up the custom scene:

This doesn't seem to be the case on visionOS 2, I tried the following code starting from an empty app template:

import SwiftUI

@main
struct SceneTestApp: App {
    var body: some Scene {
        MyScene()
        
        WindowGroup(id: "extra") {
            Text("Extra window")
        }
    }
}

struct MyScene: Scene {
    @Environment(\.scenePhase) private var scenePhase
    @Environment(\.openWindow) private var openWindow
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onAppear {
                    openWindow(id: "extra")
                }
        }
        .onChange(of: scenePhase) { oldValue, newValue in
            print("scenePhase changed")
        }
    }
}

The result was that I didn't get onChange callback if I only closed the extra window, the callback only came after I closed both windows and the whole app was suspended. Is this expected behavior?

Answered by Vision Pro Engineer in 825503022

Hey @pwgr,

The engineer in the forums is correct. With the APIs currently available you can either place the scenePhase environment variable within your App, or within your View. Reading the scenePhase environment variable from the Scene is the same as reading it from the App. I'll update the docs to remove the incorrect Scene section.

If you have a need for retrieving the scenePhase that reflects an aggregation of all the scenes in your custom scene, please file an enhancement request using Feedback Assistant providing more information as to your use case of this API. Once you file the request, please post the FB number here.

If you're not familiar with how to file enhancement requests, take a look at Bug Reporting: How and Why?

Thanks,
Michael

The result was that I didn't get onChange callback if I only closed the extra window

This is wrong, I meant that I didn't get the callback if I only closed the main window (which was the only window in MyScene).

Are you using scene phase in the extra window too? You have to implemented separately in each window. The code above only showed it in the MyScene window.

I like to set up a central bit of state to track my the open status of my scenes. I made an example of this a while back. Hope it helps! https://github.com/radicalappdev/Step-Into-Example-Projects/tree/main/Garden06

Accepted Answer

Hey @pwgr,

The engineer in the forums is correct. With the APIs currently available you can either place the scenePhase environment variable within your App, or within your View. Reading the scenePhase environment variable from the Scene is the same as reading it from the App. I'll update the docs to remove the incorrect Scene section.

If you have a need for retrieving the scenePhase that reflects an aggregation of all the scenes in your custom scene, please file an enhancement request using Feedback Assistant providing more information as to your use case of this API. Once you file the request, please post the FB number here.

If you're not familiar with how to file enhancement requests, take a look at Bug Reporting: How and Why?

Thanks,
Michael

Reading scenePhase from custom Scene
 
 
Q