NSPopover crashes on segue triggered programmatically, OSX, Xcode 8.2 - objective-c

I have a simple setup (OSX not iOS):
Two windows A and B. Window A is a splash screen, window B the main screen.
Flow is like this -> Window A on app start, opens window B on "New Project" button click.
Window B contains a button. Button is setup in IB to open a view within a popover (via segue). Segue on button click works as expected.
On some place i trigger that segue programatically (performSegueWithIdentifier) to open the same popover attached to the button. This works as expected.
[self performSegueWithIdentifier:#"showSHImportCSVPrefsViewController" sender:nil];
But: if i close window B which returns to window A and open window B again ("New project") the popover throws an error when triggered programatically even if the manual button click still works... im so confused...
[NSPopover showRelativeToRect:ofView:preferredEdge:]: view has no window. You must supply a view in a window.'

After going through the whole code it turned out it was an observer not killed.
So when i closed window B and re-opened it, the same observer was created again, triggering the programmatically segue call twice, leading to the above described situation.
Solution: removeObserver on - (void)dealloc

Related

OS X Menubar application: How to bring window to front

I am developing a menubar-only application for OS X and I am struggeling to get a settings window to show up in front of other apps.
App setup
"Menubar-only application" means:
I removed the "Is Initial Controller" from the NSWindowController in the main storyboard file. The main storyboard's window is not used in my app
I added an NSMenu to the "Application Scene" in the main storyboard. This will become my menubar menu
I set LSUIElement to YES to hide the dock icon
I set LSBackgroundOnly to NO (see NSWindow makeKeyAndOrderFront makes window appear, but not Key or Front)
When the app starts, I create an NSStatusItem and add the NSMenu from the storyboard as its menu. This all works fine - the app starts, shows no window and no dock icon but a menubar item that contains the menu from the storyboard.
Settings window
I now wanted to add a settings window that is shown when a menubar entry is clicked. I therefore:
Created a new .xib-file and added an NSWindow to it
Created a custom NSWindowController that connects the outlets and actions
Instantiated the custom NSWindowController using initWithNibNamed: on app launch
When the "Settings"-entry from the menu is clicked, I then try to bring the settings window to front using:
[self.settingsWindowController.window center];
[self.settingsWindowController.window showWindow:self];
[self.settingsWindowController.window makeKeyAndOrderFront:NSApp];
The window is shown, but not brought to the front but rather hidden behind other apps.
Any ideas how to solve this? Thanks!
You need to call:
[NSApp activateIgnoringOtherApps:YES];
(This is one of the rare occasions where it's correct to pass YES to that method.)
For Swift you can use
NSApp.activate(ignoringOtherApps: true)
I know you're asking for obj-c and already received an answer, but just incase anyone is Googling for Swift 4 implementation.
In your class that extends NSWindowController define the function:
func bringToFront() {
self.window?.center()
self.window?.makeKeyAndOrderFront(nil)
NSApp.activate(ignoringOtherApps: true)
}
Then whenever you wanna bring it up, call bringToFront().

Cocoa - How to bring particular window to come in foreground from StatusMenu

I am working on an Mac Application. I have set Application is agent (UIElement) = YES in plist, and App have a Window (lets say Popup Window) that acts as custom PopOver for StatusMenu. One more window is there (lets say Window B) that should opened on selecting a Link from StatusMenu that i have made, but Problems that I am facing are as follow:
On Application launch, When I opens status Menu It also showing Window B, that actually should not be Shown. Window B is allocated and initialised in Application Delegate.
Another Issue is When Window B is made Visible by Selecting it from StatusMenu. It appears well, Now i switch to another application so Its window is sent to background that is fine, but Whenever I click on Status Menu, It automatically comes in Front. Ideally It should only open Popup window.
Window B is opening because you might be forgot to un-check "Visible At Launch" window property in attribute inspector of interface builder
2nd issue you can resolve by activateIgnoringOtherApps set to YES before calling your window
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
[windowB showWindow:nil];

Cocoa HUD panel shows again after calling orderOut:

I'm using a NSPanel with HUD style to display some information.
There's a button inside the HUD panel, when the user clicks the button, I'll open a new window by calling:
[anotherWindowController showWindow:self];
[anotherWindowController.window makeKeyAndOrderFront];
And I want the panel disappear when the window shows, so I set the delegate of the main window, and in the windowDidResignMain callback, I called [hudPanel orderOut:nil].
The HUD panel did disappear (I can see it), but right after it closed, it reopens.
I've checked all possible orderFront: code, and none of them get called. So my hands are really tied. Is this a system level behaviour? Can anyone guide me through this?
EDIT:
I forgot to mention that, the button resides in a NSPopover. So, basically, there's a NSButton in the HUD panel. When user clicks the button, a NSPopover will show up, inside which, there's the button to bring up the new window.
Big thanks!
I had the problem. The following solved it:
[NSApp endSheet:yourPanel];
[yourPanel orderOut:self];
Use
[hudPanel performClose:nil]
(in Swift I have to use self instead of nil). I had a problem using orderOut with a popover and it was solved by using the above method.
Please add [hudPanel close] after [hudPanel orderOut:nil]
swift: hudPanel.close()
from the apple docs:
If the window is the key or main window, the window object immediately behind it is made key or main in its place. Calling orderOut(_:) causes the window to be removed from the screen, but does not cause it to be released. See the close() method for information on when a window is released.
Sometimes the window reappears during window controller inner logic, I think. I have an issue when long pressing keyboard button kills window, but shot keyDown event only hides it on the split second. After using close all goes smoothly.

Show a second window from a second .xib file in Xcode?

I am a complete noob with Xcode, but I am trying to make a small Mac application.
What I want happen, is that I press a button in the main window, and another window opens on top of that main window.
As I said, I am a complete noob, so I would prefer a step by step guide :)
It is quite simple, first of all you have to create a window with Xcode, then a WindowController after that you can link the Controller with your view(the Xib).
Then to open up a new window (lets say your window controller is called YourWindowController) just insert this code in the IBAction method that get fired by your button :
YourWindowController *controllerWindow =
[[YourWindowController alloc] initWithWindowNibName:#"You_Window_XIB"];
[controllerWindow showWindow:self];

Xcode Run IBAction when app loads

I would like to hide a window before the app has loaded. Now I know to hide a window you can use this;
[window2 orderOut:nil];
which works fine when you click on a button but what if I wont it to be hidden before or whilst the application has loaded?
So sorta need an IBAction on when the application loads
In Interface Builder, you can uncheck the box (in the window's attributes pane) that says to show the window at startup.
Or you can put that line of code in your app delegate's applicationWillFinishLaunching (or perhaps applicationDidFinishLaunching) method. (Might not work in the first one, I'm not sure.)
But I'd go with the first option, personally.