activateSceneSession (or requestSceneSessionActivation) always creates new Scene

I'm trying to implement a Help Window from Help Menu in macOS (Mac Catalyst). I have SceneConfiguration in Info.plist and multi-window enabled. Tapping Help menu opens a new Help Window on macOS. I thought it was working great!

Unfortunately, tapping Help menu again opens a new Help Window. I only want one Help window to be shown.

I expected UIApplication.shared.activateSceneSession(for: request) to use an existing UIScene if one was already present. In my experience I always get a new Scene and thus a new Window. What am I missing?

AppDelegate.swift

    func application(_ application: UIApplication,
                     configurationForConnecting connectingSceneSession: UISceneSession,
                     options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // It's important that each UISceneConfiguration have a unique configuration name.
        var configurationName: String!

        switch options.userActivities.first?.activityType {
        case UserActivity.HelpMenuActivityType:
            configurationName = SceneConfiguration.helpWindowConfiguration 
        default:
            configurationName = SceneConfiguration.defaultConfiguration
        }

        return UISceneConfiguration(name: configurationName, sessionRole: connectingSceneSession.role)
    }

override func buildMenu(with builder: UIMenuBuilder) {
    super.buildMenu(with: builder)
   ...
   builder.remove(menu: .help)
   builder.insertSibling(helpMenu(), afterMenu: .window)
}

func helpMenu() -> UIMenu {
        let children: [UIAction] = [
            UIAction(...
            ) { [weak self] action in
                self?.helpMenuTappedHandler(action)
            }
        ]
     ....
}

func helpMenuTappedHandler(_ action: UIAction) {
    let userActivity: NSUserActivity = ...
    userActivity.targetContentIdentifier = ...

    let options: UIScene.ActivationRequestOptions = .init()
    options.requestingScene = ...

    let request: UISceneSessionActivationRequest = .init(role: .windowApplication, userActivity: userActivity, options: options)

    UIApplication.shared.activateSceneSession(for: request, errorHandler: handleHelpError)
    }
Answered by dferrero in 817885022

I modified the above func to add code to detect if the Help Session already exists:

func helpMenuTappedHandler(_ action: UIAction) {
        // check if Help Window already exists before requesting one
        if let helpScene = UIApplication.shared.connectedScenes.first(where: { $0.session.configuration.name == SceneConfiguration.helpWindowConfiguration }),
           let helpWindowScene = helpScene as? UIWindowScene
        {
            let window = helpWindowScene.keyWindow ?? helpWindowScene.windows.first
            window?.makeKeyAndVisible()
            return
        }
....

}

This does seem to work, except that if the Help Window is behind the Main Window, the call window?.makeKeyAndVisible() does not bring that Window in front of the other Main window as expected...

I'm starting to wonder if I should just create the Help window as another window inside the Main UIScene instead of in its own Scene. Thoughts?

Accepted Answer

I modified the above func to add code to detect if the Help Session already exists:

func helpMenuTappedHandler(_ action: UIAction) {
        // check if Help Window already exists before requesting one
        if let helpScene = UIApplication.shared.connectedScenes.first(where: { $0.session.configuration.name == SceneConfiguration.helpWindowConfiguration }),
           let helpWindowScene = helpScene as? UIWindowScene
        {
            let window = helpWindowScene.keyWindow ?? helpWindowScene.windows.first
            window?.makeKeyAndVisible()
            return
        }
....

}

This does seem to work, except that if the Help Window is behind the Main Window, the call window?.makeKeyAndVisible() does not bring that Window in front of the other Main window as expected...

I'm starting to wonder if I should just create the Help window as another window inside the Main UIScene instead of in its own Scene. Thoughts?

Not directly related but it's close :D

I see my help Help Window shows up under the Window menu, but it has the same name as the Main Window (the app name). How can I edit the name of the window used in the Window Menu?

activateSceneSession (or requestSceneSessionActivation) always creates new Scene
 
 
Q