I've created a Mac OS X application, and during the development it was fine because I opened it with Xcode.
But now, I try to execute the executable and it's working only the first time, because after close the window, the app persists in memory. And I have to kill it with the activity monitor.
So what should I do to kill the app when I touch the red top left button on the window?
- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)application
{
return YES;
}
Override the windowWillClose method in your delegate to make it terminate the app.
- (void)windowWillClose:(NSNotification *)aNotification {
[NSApp terminate:self];
}
Related
I'm new too Xcode (5.1.1) and Mac's (OS X) and I'm trying to get my app to close when the red close button is pressed. I am using the below code to try and do it in AppDelegate.m
- (void)windowWillClose:(NSNotification *)aNotification {
[NSApp terminate:self];
}
But all this seems to do is close the window, the app itself is still running and the icon remains in the dock. Though clicking the icon does nothing and neither does launching the app again (it seems to think it is still running). I have to force shut down in order to launch the app again.
Any help would be great thanks.
If shutting down the application when the last window closes is acceptable you can use the following method in your app delegate.
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
return YES;
}
if you don't want to quit the application, you should do this :
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return NO;
}
i try to deploy the app for both 10.6 and 10.7.
i set deployment target to 10.6 and base SDK to 10.6 on XCode.
It is a status bar application, which means it doesn't have a main window.
One nsmenuitem triggers the method -(void)openCreateNewWindow which opens a nswindow.
On 10.7 it works fine but on 10.6 even if the app starts working normally, the nsmenuitem pressed doesn't open the window.
What is going wrong?
The method that opens the window looks like this:
-(void)openCreateNewWindow{
//supportWindow is a subclass of NSWindowController
supportWindow *sw = [[supportWindow alloc] initWithWindowNibName:#"createNewPanel"];
addPanel = [sw window]; //addPanel is a public var of NSWindow type
[addPanel center];
[addPanel setTitle:#"foo"];
[sw showWindow:self];
}
I added a applicationShouldOpenUntitledFile method to my application delegate, returning NO as Apple's documentation specifies. However, I'm still getting a new document on startup. What's wrong?
#implementation AppDelegate
#synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
NSLog( #"This is being called" );
}
- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender
{
NSLog( #"This never is" );
return NO;
}
#end
You're running Lion. When you ran before adding the applicationShouldOpenUntitledFile handler, a new document was created. Now, with 10.7's "Restore windows when quitting and re-opening apps", your application is restoring that untitled window, and not creating a new one as you suppose.
Close that window and re-run your application, and applicationShouldOpenUntitledFile will be called and will suppress the creation of a new untitled file.
-(void)applicationDidFinishLaunching:(NSNotification *)notification
{
// Schedule "Checking whether document exists." into next UI Loop.
// Because document is not restored yet.
// So we don't know what do we have to create new one.
// Opened document can be identified here. (double click document file)
NSInvocationOperation* op = [[NSInvocationOperation alloc]initWithTarget:self selector:#selector(openNewDocumentIfNeeded) object:nil];
[[NSOperationQueue mainQueue] addOperation: op];
}
-(void)openNewDocumentIfNeeded
{
NSUInteger documentCount = [[[NSDocumentController sharedDocumentController] documents]count];
// Open an untitled document what if there is no document. (restored, opened).
if(documentCount == 0){
[[NSDocumentController sharedDocumentController]openUntitledDocumentAndDisplay:YES error: nil];
}
}
I'm using Xcode 8.3.2 and compiling for Os X 10.11 using a storyboard for a document based app.
I noted that, if you set the window controller as initial controller, a window is created without any document and without calling applicationShouldOpenUntitledFile.
I solved removing the "is initial controller" checkbox in the storyboard.
If you're not running Lion / 10.7 or later, this can still happen if you have some other window open (even a non-Document window) when applicationShouldOpenUntitledFileshould be called.
I have a Document-based app where the AppDelegate class opens a global logging window, both for debugging purposes and for user status messages. If I have the program display that window on startup while running on OS X 10.6, applicationShouldOpenUntitledFile never gets called, even with no document windows displayed. If I turn that window off, the call is made.
Since OSX Lion, the app's state restoration may interfere with your custom preferences for this exercise.
Citing an update to Aaron Hillegass and Adam Preble's book Cocoa Programming for MacOSX:
Note that Mac OS X Lion's state-restoration features may make it tricky to observe the new document preference. You can disable state restoration by editing the Run scheme in Xcode. Open the product menu and select Edit Scheme. Select the Run RaiseMan.app scheme, change to the Options pane, and check Disable state restoration.
I've been trying to submit an application for the Apple App store and the reviewer claims that my initial notice window (which is modal) does not go away when they hit the accept button. Now I've tested it on several machines (even clean 10.7.1 installations) and have not seen this behavior (it works great for me).
My code to display this window:
- (IBAction) doAlert:(id)sender {
if(self.alertVC == nil) {
self.alertVC = [[[AlertVC alloc] initWithWindowNibName:#"AlertVC"] autorelease];
}
[NSApp runModalForWindow:self.alertVC.window];
}
and the code with which I close it looks like this:
-(IBAction)closeWindow:(id)sender {
[self close];
[NSApp stopModal];
}
Anyone have any idea why this works 100% in all my tests but for the Apple testers the window does not go away? (It stays open in the foreground even though the application continues and they can interact with the application as normal again.
The only thing I see, that may cause the error is, that you are not closing the window, but the controller (or who else provides the method closeWindow)
If closeWindow is a method of the same class than doAlert the code should look like:
-(IBAction)closeWindow:(id)sender {
[self.alertVC.window performClose:self];
[NSApp stopModal];
}
I know the answer is late and you probably have found a solution, but I provided the answer for all those stumbling over the snippet and wondering, why it happens to them as well.
I'm running into a few problem with a background application that uses LSUIElement=1 to hide its dock item, menu bar and prevent it from appearing in the Command-Tab application switcher.
It seems to be a Snow Leopard only problem.
The application places an NSStatusItem in the menu bar and pops up a menu when clicked on. Selecting "Preferences..." should bring up an NSWindow with the preferences.
The first thing that doesn't seem to work is that the Window does not get ordered in at the front, but appears behind all other application windows.
I tried to fix this by calling
[[NSApplication sharedApplication] activateIgnoringOtherApps: YES]
but that didn't work.
After a while I figured out that the menu is blocking the message to the run loop from being sent, so I wrote another method on the MainController and sent the message with a delay:
[self performSelector:#selector(setFront:)
withObject: [preferencesController window] afterDelay:1.0];
-(void)setFront: (id) theWindow {
[[NSApplication sharedApplication]activateIgnoringOtherApps:YES];
[theWindow orderFrontRegardless];
[theWindow makeKeyWindow];
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
Note the send-every-possible-message-to-make-it-do-what-it-should-be-doing-approach.
This works, kind-of, the window is brought to the front on top of all other windows from all apps, BUT most of the time it isn't active, meaning it's title bar is greyed out. Clicking on the title bar won't make the window active either. Clicking INSIDE of the window will make it active!?
This all didn't seem to be a problem in Leopard; just calling activateIgnoringOtherApps and making the window key seemed to work just fine.
In Snow Leopard there is a new API designed to replace LSUIElement that is supposed to emulate its behaviour:
http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html
I've played around with that, but it's SL-only and I haven't been able to get LSUIElement being set.
That's strange - I'm writing a LSUIElement application under Snow Leopard, and I didn't have such problems as you've described... I did have the problem that the newly created window didn't appear at the front, but I fixed it by calling activateIgnoringOtherApps. This was all I had to do to make it work as it should:
[NSApp activateIgnoringOtherApps: YES];
[preferencesWindow makeKeyAndOrderFront: self];
I didn't even touch anything that had 'policy' in the name.
After posting the question in desperation, I did continue looking and did eventually find the solution. Since this stumped me for a few days and there seems to be no other answer out there that google can find, I'll explain the solution for "future generations".
Snow Leopard adds a new NSApplication presentationOptions API:
http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html
This is supposed to simulate the way that LSUIElement works, but provide more developer control. Unfortunately, the simulation isn't perfect so there is a change of behaviour between 10.5 and 10.6.
In particular, if your application has the LSUIElement = 1 line in its info.plist, Snow Leopard will initialize "the application’s presentationOptions .. to an equivalent combination of NSApplicationPresentationOptions flags instead".
Only it doesn't really. It sets the new NSApplication setActivationPolicy to NSApplicationActivationPolicyAccessory:
"The application does not appear in the Dock and does not have a menu bar, but it may be activated programmatically or by clicking on one of its windows. This corresponds to value of the LSUIElement key in the application’s Info.plist being 1."
Despite the mention of being activated programatically, activateIgnoringOtherApps: is simply ignored completely.
The solution is to set the activation policy to "regular":
[[NSApplication sharedApplication] setActivationPolicy: NSApplicationActivationPolicyRegular];
Of course, you can only do this if you use the 10.6 SDK as Base SDK, something few people want to do at the moment, so below is a 10.5-safe way of doing this:
NSApplication* app = [NSApplication sharedApplication];
if( [app respondsToSelector: #selector(setActivationPolicy:)] ) {
NSMethodSignature* method = [[app class] instanceMethodSignatureForSelector: #selector(setActivationPolicy:)];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: method];
[invocation setTarget: app];
[invocation setSelector: #selector(setActivationPolicy:)];
NSInteger myNSApplicationActivationPolicyAccessory = 0;
[invocation setArgument: &myNSApplicationActivationPolicyAccessory atIndex: 2];
[invocation invoke];
}
I hope somebody will find this useful.