How to properly quit application, call exit(0)? - cocoa

I'm not sure which is the right way, right now I'm just calling exit(0) when a user clicks on the exit button.

Use NSApplication's terminate method. For example:
[NSApp terminate:self]
Documentation is available here.

The previously given answer is deprecated since 10.10 and this question is the first thing that turns up for cocoa quit application, so use this instead (Swift):
NSApplication.sharedApplication().terminate(self)
Note: As of now it's the following:
NSApplication.shared().terminate(self)

I always terminate App the safe way.
[NSApp performSelector:#selector(terminate:) withObject:nil afterDelay:0.0];
This will put the event in the next loop.

Related

cocoa - executing stuff, need to open window, get input, then continue w/o reentering runloop

Is there any way to do this?
Right now, I get called, I'm doing things, I have to open a window to ask for input, then I have to FINISH doing things before I return from the original call.
If I enter the runloop for the window, it never ends or returns control to me.
What am I missing here?
I got it -- [NSApp runModalForWindow: window] -- that runs JUST the loop for the window, and when you stop it, control returns to you, leaving the main run loop undisturbed.
What I was doing was [NSApp run], which runs everything, and so when the window issued the stop, everything did.

How to make a function been called every frame in the cocoa programming?

I know cocoa application has a main run loop, how to make a function been called every frame? I mean this function should be called every process of the main loop. Is that through the -(void) run of the + (NSRunLoop*) currentRunLoop;?
You can call getCFRunLoop to get the Core Foundation RunLoop. Then it's just a matter of adding an observer to the CFRunLoop. See the docs for this function:
CFRunLoopAddObserver()
I'm assuming you are targeting OSX since the tag is cocoa and not cocoa-touch so if you want to synchronize with every screen frame update you should check out CVDisplayLink
I know it's been quite some time. Anyway this might come useful for someone who stumbled upon here like me.

Hiding NSPanel through a timer in Cocoa

I am new to Cocoa and would like to know how to hide an NSPanel when a timer tick, I have tried to call
[myNSPanel orderout:self], the code runs but the panel is still there. Do I need to do something different? Thanks in advance.
For one thing, the selector is orderOut:, and selectors are case-sensitive, so if your code actually says orderout:, then you're getting a does-not-respond-to-selector exception (which you can see in the Debugger Console) and that's why your code isn't working.
If it still doesn't work after you fix that, make sure myNSPanel (which I assume is an outlet) is actually hooked up to the panel in question. A very common mistake is to forget to connect the outlet; when you do this, the pointer in the outlet variable is nil, and a message to nil simply does nothing.
You can check this by logging the pointer: NSLog(#"%p", myNSPanel);. After that statement runs, the Debugger Console will contain a line telling you what pointer was in the myNSPanel variable. If it's 0x0, that's nil.

How can I tell my Cocoa application to quit from within the application itself?

I'm looking for a good way to tell my Cocoa application to quit itself. Rest assured that this will not be used for production code. I'm just looking for an easy way to run one test and then close the application during debugging.
I have found that exit(0); will close the app, but it bypasses all of the normal application exit procedures, and I would like to keep all of them in place.
Essentially I want things to work as if a user pulled "Quit" from the menu, but I want it to happen automatically after I have finished with my test.
My code currently looks like this:
#if (SUPERFANCY_TESTING_MODE)
[self doSomething];
exit(0); // <-- I need something better to go here
#endif
You can pretty much rest assured that your app is going to get killed at least some of the time. Thus, defending against exits the like of exit(0); is required.
However, NSApplication implements the -terminate: method.
[NSApp terminate: nil]; ought to do what you want.
I would generally suggest posting it via -performSelector:afterDelay: with a delay of 0.0 to force it to happen at the top of the next pass through the event loop.
Example:
[NSApp performSelector:#selector(terminate:) withObject:nil afterDelay:0.0];

RBSplitView has delayed reload of autosaved view positions

I really enjoy using RBSplitView, an open source replacement for NSSplitView, but I have a problem in my shipping app and am experiencing it again in a new project.
The problem is I'm telling the RBSplitView to autosave its position state by giving it an autosave name. When my app launches the RBSplitView doesn't seem to honor the saved state till a second after the window is drawn.
I've spent the night trying to debug the behavior but have had little success. Anyone out there use this lib and have some advice?
You can scrub this quicktime movie to the issue at work:
http://media.clickablebliss.com/billable/interface_experiments/rbsplitview_delayed_autosave_reload2.mov
I've still been unable to figure out why this is happening but I do have a workaround.
First, make sure your main window is not visible at launch and then at the end of applicationDidFinishLaunching in your app delegate add something like:
[mainWindow performSelector:#selector(makeKeyAndOrderFront:) withObject:self afterDelay: 0.1];
The delay is the key. If you just tell the window to makeKeyAndOrderFront: I still see the issue. However as long as it has a beat of time it looks good.
This likely is happening because the RBSplitView instance needs to wait until it's first moment to get to set its frame to the autosaved value, which happens to be after the user can see it. This 0.0-delay trick simply delays showing the window until the very next runloop, which gives the split view a chance to do its magic (and other views) so that when the user sees the window, it's already nice and sexy. So just do the delay at 0.0 and you'll be fine.
I have a similar, but slightly different workaround in my app that uses RBSplitView. In applicationDidFinishLaunching:, I call adjustSubviews on the split view before calling makeKeyAndOrderFront: on the window that contains it. This seems to knock the split view in to order before it gets displayed on the screen.

Resources