NSPopover to start in a detached state
Here is the trick.
Use the required delegate method detachableWindowForPopover:
to do the work for you, like:
- (void) showPopoverDetached
{
NSWindow* detachedWindow = [self detachableWindowForPopover:nil];
[detachedWindow.windowController showWindow:nil];
}
Seems that the Apple engineers implemented detachableWindowForPopover:
on a pretty smart way, I guess it uses the content view controller class, and will always create a singleton like instance of the detached window.
Once detachableWindowForPopover:
has called the presented window instance will be re-used no matter when and why it is called, called it directly (from a func like my sample above) or indirectly (e.g. when you drag out, detach, the popover from its original position)
This way they can prevent a popover from being detached 'twice' and we can also implement the detached way programmatically, nice job from them!
Here is a tiny demo of how it works in a real life (tested on macOS 10.13 - 13.0)
https://imgur.com/a/sfc7e6d
How to make NSPopover 's detached window become modal window
I kind of found the solution myself. It looks working fine now.
To do this, after the detached window ordered to front and become key window, the following code will make it a modal window (where currModalSession is an iVar defined by myself).
- (void)windowDidBecomeKey:(NSNotification *)notification {
if (notification.object == detachedWindow) {
if (!detachedWindow.isModalPanel) {
currModalSession = [NSApp beginModalSessionForWindow:detachedWindow];
[NSApp runModalSession:currModalSession];
}
}
}
Also, you have to end each Modal Session you have opened. So the following code does the job:
- (void)windowWillClose:(NSNotification *)notification {
if (notification.object == detachedWindow) {
if (currModalSession) {
[NSApp endModalSession:currModalSession];
}
}
}
Note: you have to use Modal Session here rather than runModalForWindow for two reasons:
- otherwise the main window won't be blocked right away. I don't quite get the reason yet. One possible explanation is: runModalForWindow will not just block user interactions but also internal communications, so main window might need more time to be ready.
- if you plan to run another framework modal dialog (e.g. NSOpenPanel) from the detached window, when return, the detached window will become key window before the new modal dialog close, namely runModalForWindow will freeze another to be closed window. That means to be closed window won't be closed.
After detaching an NSPopover the next appearance is missing callout
I think creating a new popover each time is the way to go. It's a cheap operation since the content of the popover is not recreated everytime, just the popover itself.
Getting access to NSPopover window to set level?
NSPopover
is a subclass of NSObject
, not NSWindow
, so setting the window level is not officially supported.
You could try getting the window like this:
NSWindow* popoverWindow = yourPopover.contentViewController.view.window;
I have no idea whether you can then successfully set the level though.
NSStatusItem with NSPopover and NSTextField
Yes, just add the NSWindow+canBecomeKeyWindow (.h and .m) files to your project, and it should work. I'm using this technique in an app I'm currently developing, and it works fine. Make sure NSWindow+canBecomeKeyWindow.m is listed under "Compile Sources" in your project's Build Phases.
As an aside, I'm having other issues using NSPopover to show a window from an NSStatusItem. I haven't actually tried using it in my project, but this looks promising as an alternative.
Related Topics
Swift: Copy Information Selected by User in Abpersonviewcontroller to Dictionary
In What Situation Would One Use Expectationfornotification in Swift Testing
Refreshing Auth Token with Moya
How to I Access Argv and Argc in Swift
Gcd Pattern for Chaining Async Operations While Piping the Results
Arkit - How to Display the Feed from a Virtual Scncamera Placed on Scnplane
Why iOS13 Login with Facebook Does Not Work
Drawing a Gradient Color in an Arc with a Rounded Edge
How to Load the Photo Library into Uicollectionview? Swift
Firebase Auth Internal Error on Login Attempt
Binding 2 Properties (Observe) Using Keypath
Swift Packages and Conflicting Dependencies
Weak Method Argument Semantics
Require Associatedtype to Be Representable in a @Convention(C) Block
iOS 12 Errors: Appears to Be from a Different Nsmanagedobjectmodel Than This Context'S
Non Exhaustive List When Handling Errors Inside a Class Function in Swift