How do I quit a mac application programmatically? - objective-c

I need to add a quit-button to my application that runs from the menubar in mac.
How do I programmatically quit an application in mac?

There is a simpler form to quit from code:
[NSApp terminate:self];
But as you're adding a button, all you have to do is to control drag from your button to the Application icon and connect the method terminate:.

[[NSApplication sharedApplication] terminate:self];

Try the following:
[NSApp terminate: nil];

In some case you cannot close app when call [NSApp terminate:self];. Like when showing NSAlert as sheet on the doc window (NSAlert -beginSheetModalForWindow:completionHandler:) ...
You can close all window and alert before call terminate, like following code:
for (NSWindow *window in [NSApplication sharedApplication].windows) {
[window close];
}
[NSApp terminate:self];

Related

Close WindowController Without loosing Data in objective c

So i have a windowController which i pop up using NSApp this window is called from mainWindowController.
ScriptSettingWindowController *mySettings = [[ScriptSettingWindowController alloc]initWithWindowNibName:#"ScriptSettingWindowController" owner:self];
[NSApp runModalForWindow:[mySettings window]];
There are other UIElements which gets displayed only when using Owner:self. When using owner:self it takes over mainWindowController.
enter image description here
When i close the NSApp The control returns to the mainWindowController. But ends up crashing the application. I believe the control has to be returned back to mainWindowController before closing the NSApp.
To close the modal i use
[NSApp stopModal];
[NSApp orderOut:self];
[NSApp close];
but they do not close the popup.
[[self window] close];
[[self window] close]; this does close the window along with some variables being cleared and crashing the app.
Im dealing with an old project here and have no clue about mac development. Any help would be appreciated. thanks in advance

Unable to focus on NSTextFields from Modal window

I currently have a window open which was opened via:
// FirstWindowController
[self showWindow:self];
[[self window] makeKeyAndOrderFront:self];
[NSApp runModalForWindow:[self window]];
And upon click of a button I'd like to hide FirstWindowController via:
// FirstWindowController
[self.window orderOut:self];
And then show my second window:
// SecondWindowController
[self showWindow:self];
[[self window] makeKeyAndOrderFront:self];
[NSApp runModalForWindow:[self window]];
The first window disappears correctly, and the second window appears. But I can't actually use the NSTextFields in the input. But I can click the cancel button to hide SecondWindowController and give focus back to FirstWindowController.
Why can't I click any of the NSTextField elements?
I had the same problem. It worked when the window had a title bar and otherwise not. It seems like that a window needs to have a title to become a keyWindow.
The workaround for this is to make a subclass of NSWindow and override -canBecomeKeyWindow:
(BOOL)canBecomeKeyWindow {
return YES;
}

Display a sheet but still let my main app do work

The loadFile method starts a NSTimer to load an process a file over time without blocking the application in a while loop. This timer is not firing with the first bit of code, and is with the second bit. The issue is the second bit shows the sheet as a panel style window, not as a sheet.
How do I get a sheet that can still do work?
Show Sheet but no work is done
[self.sheetView loadFile:filename];
[[NSApplication sharedApplication] beginSheet: self.sheetView
modalForWindow: self.window
modalDelegate: self
didEndSelector: nil
contextInfo: nil];
[[NSApplication sharedApplication] runModalForWindow: self.sheetView];
Show window and work is done
NSModalSession session = [NSApp beginModalSessionForWindow:self.sheetView];
NSInteger result = NSRunContinuesResponse;
[self.sheetView loadFile:filename];
// Loop until some result other than continues:
while (result == NSRunContinuesResponse)
{
// Run the window modally until there are no events to process:
result = [NSApp runModalSession:session];
// Give the main loop some time:
[[NSRunLoop currentRunLoop] limitDateForMode:NSDefaultRunLoopMode];
}
[NSApp endModalSession:session];
Is there a reason why NSThread can't be used? That's the obvious answer ...

Open alert box (NASlert) with a delegate and block all other windows?

Is there a way to open a NSAlert window, set a delegate for didEnd callback and while the alert is shown, all other windows should be "disabled" (can the window itself but not push any button or change any text)?
In your NSAlert code add
NSModalSession session = [NSApp beginModalSessionForWindow:theWindow];
[NSApp runModalSession:session];
// NSAlert stuff here ...
In your didEnd callback add
[NSApp endModalSession:session];
For more information about modal windows read NSApplication's "Managing the Event Loop" section.
Update:
Here is a sample code from Apple's doc showing how to run modal without callbacks.
NSModalSession session = [NSApp beginModalSessionForWindow:theWindow];
for (;;) {
if ([NSApp runModalSession:session] != NSRunContinuesResponse)
break;
[self doSomeWork];
}
[NSApp endModalSession:session];

Can't open a sheet on a window twice

I'm opening a sheet on a window , the first time the sheet opens
correctly, but if I close it, and try to open again it doesn't work, I
just get the system alert sound.
- (IBAction) showSpeedSheet:(id)sender
{
[NSApp beginSheet:addEditPackagePanel
modalForWindow:[[NSApp delegate] window]
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
}
-(IBAction)endSpeedSheet:(id)sender
{
[NSApp endSheet:addEditPackagePanel];
[addEditPackagePanel orderOut:sender];
}
I can't find what's wrong, the app doesn't print any error on the log.
A delegate is not required.
The beep occurs because the system believes there is already a sheet open on the window (whether or not that sheet is technically visible). It's not the greatest error reporting, but that's what it is.
In my code sheets have window controllers and I do both of the following steps in every action that is attached to a sheet-closing button:
[NSApp endSheet:[windowController window]];
[windowController close];
With these steps, subsequent sheets are able to display without beeping.
I think you may need to implement the modal delegate and didEndSelector. The orderOut should be called from the did-end selector.
[NSApp beginSheet:addEditPackagePanel
modalForWindow:[[NSApp delegate] window]
modalDelegate: self
didEndSelector: #selector(didEndSheet:returnCode:contextInfo:)
contextInfo: nil];
and
- (void)didEndSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void*)contextInfo
{
[sheet orderOut:self];
}
I believe control is sent to the did-end selector has soon as endSheet is called.