This issue persists on watchOS 8 Beta. It's not just that the onChange
is not called. It is also not updating the variable at all (in some cases). As this seems to be unreliable I went for this solution, which is not recommended, but 100% reliable:
It just serves to send notifications when the state of the app changes. For watchOS this would be:
class ExtensionDelegate: NSObject, WKExtensionDelegate {
func applicationDidBecomeActive() {
NotificationCenter.default.post(name: Notification.Name.App.scenePhaseChanged, object: nil, userInfo: ["scenePhase": ScenePhase.active])
}
func applicationWillResignActive() {
NotificationCenter.default.post(name: Notification.Name.App.scenePhaseChanged, object: nil, userInfo: ["scenePhase": ScenePhase.inactive])
}
func applicationDidEnterBackground() {
NotificationCenter.default.post(name: Notification.Name.App.scenePhaseChanged, object: nil, userInfo: ["scenePhase": ScenePhase.background])
}
}
This serves as a replacement for the actual key, which is not updated reliably.
extension EnvironmentValues {
var customScenePhase: ScenePhase {
get {self[CustomScenePhaseKey.self]}
set {self[CustomScenePhaseKey.self] = newValue}
}
}
private struct CustomScenePhaseKey: EnvironmentKey {
static let defaultValue = ScenePhase.inactive
}
var appStateChangeNotification = NotificationCenter.default.publisher(for: Notification.Name.App.scenePhaseChanged)
//....
.onReceive(self.appStateChangeNotification, perform: { notification in
let newScenePhase: ScenePhase = notification.userInfo?["scenePhase"] as? ScenePhase ?? .active
guard newScenePhase != self.scenePhase else {return}
self.scenePhase = newScenePhase
})
ContentView()
.environment(\.customScenePhase, self.scenePhase)
I hope this sample code helps anyone with similar issues