iosswiftmac-catalyst

Get the focused/current window among multiple windows - Mac Catalyst


I am working on UIMenuBuilder in Mac Catalyst. Because my app supports multiple scenes with different classes of UISceneDelegate, I need to validate UICommands (func validate(_ command: UICommand)) depending on the focused window. I have been trying a few solution, however no one works.

1.

for scene in UIApplication.shared.connectedScenes.filter({$0.activationState == .foregroundActive}) {
    if let delegate = scene.delegate as? SceneDelegate {
          //...
    } else if let delegate = scene.delegate as? DetailSceneDelegate {
          //...
    }
}

In this case, it turns out that each scene (window) has the state foregroundActive - when windows are visible.

2.

for scene in UIApplication.shared.connectedScenes {
    if let delegate = scene.delegate as? SceneDelegate {
          print("SceneDelegate: ", delegate.window?.isKeyWindow)
    } else if let delegate = scene.delegate as? DetailSceneDelegate {
          print("DetailSceneDelegate: ", delegate.window?.isKeyWindow)
}

Here, the app finds each window as a key one.

Thank you in advance!


Solution

  • The simplest solution is to add func validate(_ command: UICommand) to the various view controller subclasses being used by your different scene delegates. The validate(_ command: UICommand) method is from UIResponder. This means that when a menu is about to be presented, each member of the current responder chain has its validate(_ command: UICommand) method called. So for whichever screen is currently the frontmost, validate(_ command: UICommand) will be called as follows:

    view -> root view controller -> window -> app delegate

    If the window's root view controller has child view controllers then each child view controller is also part of that chain.

    So instead of trying to work out which scene represents the focused window, simply put the logic in the appropriate view controller classes.

    Be sure each implementation of validate(_ command: UICommand) calls super.validate(command) so each level of the chain is given the chance to validate the command.