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)
}
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?