Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Track when user comes back to app or moves focus away from Mac Catalyst window

I would like to use the delegate methods of the UISceneSession lifecycle to help inform my Mac Catalyst app when the user moves their focus away from the app (window) and then comes back to the app (window).

When the app first launches on Mac sceneWillEnterForeground and sceneDidBecomeActive are successfully called, however when I focus on another app then delegate methods such as sceneWillEnterForeground are not called. Why?

like image 368
Cesare Avatar asked Sep 17 '25 07:09

Cesare


2 Answers

If you check NSWindowDelegate.windowDidBecomeMain(_:) you'll notice that its parameter is a notification whose name is NSWindowDidBecomeMainNotification.

So, you can observe that notification to get notified whenever a window in your app becomes focused:

NotificationCenter.default.addObserver(forName: .init("NSWindowDidBecomeMainNotification"), object: nil, queue: nil) { notification in
    print("This window became focused:", notification.object)
}

And you can also observe NSWindowDidResignMainNotification to get notified when a window in your app lost focus.

like image 96
Hejazi Avatar answered Sep 23 '25 11:09

Hejazi


Thanks to https://developer.apple.com/forums/thread/681591 , I discovered that traitCollection.activeAppearance is very useful for this purpose.

In SceneDelegate, you can add:

func windowScene(_ windowScene: UIWindowScene, didUpdate previousCoordinateSpace: UICoordinateSpace, interfaceOrientation previousInterfaceOrientation: UIInterfaceOrientation, traitCollection previousTraitCollection: UITraitCollection) {
    if #available(macCatalyst 14.0, *) {
        let newActiveAppearance = windowScene.traitCollection.activeAppearance
        if newActiveAppearance != previousTraitCollection.activeAppearance && newActiveAppearance == .active {
            //do stuff
        }
    }
}

Or in your ViewController, you can add:

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    if #available(macCatalyst 14.0, *) {
        let newActiveAppearance = traitCollection.activeAppearance
        if newActiveAppearance != previousTraitCollection.activeAppearance && newActiveAppearance == .active {
            //do stuff
        }
    }
}
like image 20
salami Avatar answered Sep 23 '25 11:09

salami