How to close a new window in macOS development? - objective-c

I am new to macOS application development.
I have a main window and a custom window called ImageSetter, both have windowcontroller.
In the main window, I have a button, whose action is to open a new window by:
ImageSetter *anImageSetter = [[ImageSetter alloc] initWithWindowNibName:#"ImageSetter"];
[anImageSetter showWindow:self];
On the window of ImageSetter, I want to attach a button, whose function is to close the ImageSetter window. I tried to use
[aButton setTarget:self];
[aButton setAction:#selector(closeItself)];
and
- (void)closeItself{
[self.window close];
}
in the implementation of ImageSetter.
But I figured that I can't close it by using that button.
Help!
Thanks.

First of all, a standard window already has a button to close it in the title bar. If at all possible, you should use the standard controls.
If you have a button in a window, and all you want that button to do is close its window, simply send the performClose: message up the responder chain:
// [aButton setTarget:nil/* first responder */]; -- already nil, nothing to set
[aButton setAction:#selector(performClose:)];
The button will send the -performClose: message to the first object in the responder chain that implements to that message, which in your case should be the window that contains the button.
If you want to be explicit about the target, you can set it directly:
[aButton setTarget:aButton.window];

Related

Close window programmatically

For a Cocoa application on a Mac I need ti display some windows when the use click on the associated button. I can display the window using this :
-(void)popView:(NSString *)viewName {
_windowController = [[NSWindowController alloc] initWithWindowNibName:viewName];
[_windowController showWindow:nil];
}
In the new window I have a Push Button "Cancel" and Another "Save". I want to perform some queries in a database when the "Save" button is pressed and close the window when the "Cancel" button is pressed.
I can close the window while dragin it from the xib file (The "outlet menu" when you right-click on the window)
But I can't use this for the "Save" button.
I tried [self performSelector:#selector(performClose:)]; but I got an error message :
[AddProductViewController performClose:]: unrecognized selector sent
to instance 0x107f64900
Same for [[[self view] window] close];
I lack of ideas how to solve it, this is my very first Mac application.

Open and close NSWindow with NSButton through NSWindowController?

I've got a custom NSButton that I'm actually sticking in an NSStatusItem. When the NSButton is clicked, it launches my window. When the NSButton is clicked again, the window should close.
If the window is open, it appears as if the NSButton stops responding (or doesn't receive) click events! Here's the relevant code:
[statusItem setView:myCustomButton];
[myCustomButton setAction:#selector(showWindow:)];
- (void)showWindow:(id)sender {
if(!myWindowController) {
myWindowController = [[MyWindowController alloc] initWithWindowNibName:#"MyWindow"];
}
[myWindowController showWindow:statusItem];
[myWindowController.window orderFront:nil];
}
Am I doing something crazy? If I set a breakpoint in the above, it is hit when the button is clicked the first time but is not hit when the button is clicked again.
I'm guessing that you're not setting a target on the button. If a button has an action but no target, it gets sent up the responder chain. When the new window is shown, the responder chain is probably being changed, which means your action is being sent to a different place.
tl;dr: try setting a target on the button.

Opening a new window and waiting for it to close

I have a Mac OS X app written in objetive-c Cocoa. You can see most of the code in this previous question. Essentially you click a button on the main window (the app delegate) and it opens another window where the user can enter information.
In the following code (that gets called when the user press the button in the app's main window)
- (IBAction)OnLaunch:(id)sender {
MyClass *controllerWindow = [[MyClass alloc] initWithWindowNibName:#"pop"];
[controllerWindow showWindow:self];
NSLog(#"this is a log line");
}
The NSLog line gets printer immediately after I called showWindow. Is there any way to wait until controllerWindow is closed to continue with the NSlog?
The reason for this is that the user set's a value on the new window I opened and I need to collect that value on the same OnLaunch so I need to wait.
I know that modal windows are bad form in Mac, but I have no control over this feature.
I've tried with
[NSApp runModalForWindow:[controllerWindow window]];
and then setting the popup window to
[[NSApplication sharedApplication] runModalForWindow:popupwin];
and it works but then the focus never gets passed to the main window anymore
Thanks!
If you want the window to be modal for your application, use a sheet: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Sheets/Tasks/UsingCustomSheets.html
However, there is no way to suspend execution of a method while the sheet is displayed, this would be tantamount to blocking the current run loop. You would have to break you code into the begin and end methods as described in the linked documentation.
Here are the steps you need to follow:
In TestAppAppDelegate create an NSWindow outlet to hold your sheet and an action to dismiss the sheet
Create a nib with an NSWindow as the root object. I think you already have this in "pop". Set the Visible at Launch option to NO (this is very important)
Set the file's owner of this nib to TestAppAppDelegate and connect the window to your new outlet, and the close button to your new action
In your method to launch the sheet (OnLaunch), use the following code:
(ignore this it's to make the code format properly!)
if(!self.sheet)
[NSBundle loadNibNamed:#"Sheet" owner:self];
[NSApp beginSheet:self.sheet
modalForWindow:self.window
modalDelegate:self
didEndSelector:#selector(didEndSheet:returnCode:contextInfo:)
contextInfo:nil];
Your close button action should be [NSApp endSheet:self.sheet];
Your didEndSheet: method should be [self.sheet orderOut:self];
You can use UIVIew method animateWithDuration:delay:options:animations:completion: to accomplish this.
You said you want the next line to execute once the window is closed, rather than after it is opened. In any case, you may end the OnLaunch method this way:
- (IBAction)OnLaunch:(id)sender {
MyClass *controllerWindow = [[MyClass alloc] initWithWindowNibName:#"pop"];
[controllerWindow animateWithDuration:someDelay:options: someUIAnimationOption
animations:^{
[controllerWindow showWindow:self]; // now you can animate it in the showWindow method
}
completion:^{
[self windowDidFinishShowing]; // or [self windowDidFinishDisappearing]
}
}
- (void) windowDidFinishShowing {
NSLog(#"this is a log line");
}

How to open a window on click on NSStatusItem?

I'm pretty new to cocoa, so please excuse me for any stupid mistakes I make.
I have a NSStatusItem, which I want to use to open up a menu. However as far as I know and have heard across different forms, without a custom view you are restricted to just a pop down menu. Is this true? And if so how do you make a custom view to do something (e.g. open a window in my case)? Thanks for any help.
No, it is not true. You need to set up the target and action for the status item to call a method which does what you want (opens the window).
// This goes where you set up the status item
NSStatusItem *statusItem; // You need to get this from the status bar
[statusItem setTarget:self];
[statusItem setAction:#selector(openWindow:)];
// This method is called when the status item is clicked
- (void)openWindow:(id)sender {
NSWindow *window = [self window]; // Get the window to open
[window makeKeyAndOrderFront:nil];
}
You may also want to call [NSApp activateIgnoringOtherApps:nil]; to your openWindow: method to ensure that the window you open is not behind some other application's window.

Creating a Modal Dialog or Window in Cocoa Objective-C?

I need to create an modal dialog, which is to loaded from a nib file and should be displayed on a button click in the main window.
I can create a custom window in a nib file and load the custom dialog on button click, but it's not a modal dialog. I can switch back to the main window.
MyWindowController is the NSWindowController subclass.
I used the code below to display my window in response to the button event:
MyWindowController *pController = [[MyWindowController alloc]
initWithWindowNibName:#"nibfilename"];
[MyWindowController showWindow:self];
There are several ways to do this — and in fact two different kinds of modal dialog in OS X: application-modal and window-modal. Using the wrong one will annoy people. One is a sheet, which is attached to the window that it affects (save dialogs are an example of this). The other is application-modal, which blocks the whole application (open dialogs work this way, since they don't apply to any window that exists yet). Apple's sheet documentation should help get you oriented.
Thank you...
(Example).
Create a nib with name "About"
if(pAbtCtrl == nil)
pAbtCtrl = [[AboutWindowController alloc] initWithWindowNibName:#"About"];
pAbtWindow = [pAbtCtrl window];
[NSApp runModalForWindow: pAbtWindow];
[NSApp endSheet: pAbtWindow];
[pAbtWindow orderOut: self];