iPad menu bar and multiple windows

I'm trying to support the new menu bar in iPadOS 26.

In AppDelegate I do this. I want to this to be a global command, which can work regardless of which view controller is currently visible, so I let the AppDelegate handle the selector (if there's a better way let me know).

UIMainMenuSystem.shared.setBuildConfiguration(config) { builder in
            let createCollectionCommand = UIKeyCommand(
                title: String(localized: "Create Collection"),
                image: UIImage(systemName: "folder.badge.plus"),
                action: #selector(AppDelegate.showCreateCollectionViewController),
                input: "c",
                modifierFlags: .control
            )
            
            builder.insertElements([createCollectionCommand], atEndOfMenu: .file)
        }

This works mostly.

A problem arrises when I have multiple windows open at the same time. I need a way to determine the currently active window scene from AppDelegate to display a sheet on that window's root view controller.

There's stuff like this, but unfortunately all visible windows have activationState == .foregroundActive, so I cannot use that.

    guard let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene else { return }

So, how do I do multi-window global commands? I'm basically looking for something like the "Create Playlist" command in the Music app.

Answered by Frameworks Engineer in 851523022

When finding a target for the command's action, UIKit begins the responder search at the focused item/first responder in the active window scene's key window, then traverses up the responder chain all the way to the AppDelegate. So you can do this by having the UIWindowScene itself be the target for the action, since the responder chain traversal will eventually traverse up to the window scene level (and that window scene would be the active window scene).

That being said, it may be easier to have this handled slightly deeper than the window scene, for example the root view controller of the primary window of the window scene. That root view controller would generally be expected to always be in the responder chain, so the command should still be performable always. The advantage is that the root view controller is likely better equipped to handle the command (such as knowing how to handle creating a new playlist, compared to something like the AppDelegate or UIWindowScene). It would also mean you wouldn't have to subclass UIWindowScene just to have it handle the action.

Accepted Answer

When finding a target for the command's action, UIKit begins the responder search at the focused item/first responder in the active window scene's key window, then traverses up the responder chain all the way to the AppDelegate. So you can do this by having the UIWindowScene itself be the target for the action, since the responder chain traversal will eventually traverse up to the window scene level (and that window scene would be the active window scene).

That being said, it may be easier to have this handled slightly deeper than the window scene, for example the root view controller of the primary window of the window scene. That root view controller would generally be expected to always be in the responder chain, so the command should still be performable always. The advantage is that the root view controller is likely better equipped to handle the command (such as knowing how to handle creating a new playlist, compared to something like the AppDelegate or UIWindowScene). It would also mean you wouldn't have to subclass UIWindowScene just to have it handle the action.

Thanks. That seems like a reasonable approach that I totally did not think about. I now let my root view controller handle this and it works perfectly fine.

iPad menu bar and multiple windows
 
 
Q