0

So I need to register a function on OSX (using Xcode / objective C) that will register a particular function to be called whenever the program terminates.

I ran into this but i guess that's for iOS and not for OSX.

I replaced UI with NS and gave it a shot, but it did not work.

NSApplication *app = [NSApplication sharedApplication];
[[NSNotificationCenter defaultCenter]
 addObserver:self
 selector:@selector(applicationWillTerminate:)
 name:BeCalledOnExit object:app];

but that is not compiling. it says something on name: being an undeclared identifier when it is clearly on the .h & .m file before the function.

i ran into another chap who used this:

-(BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *) sender{
return TRUE
}

but it doesnt work for me as my app is a complete status bar app.

Basically i'm creating some temp files during my app and just before quitting, i want to make sure that my app is clearing out these files. I am putting it in /tmp/.. Woudn't want too much space to be taken.

i would really like to have a solution like in gcc/python,

atexit(functionName);
Community
  • 1
  • 1
Wingston Sharon
  • 1,030
  • 2
  • 11
  • 21
  • 1
    So why not just use atexit? It is plain C function. – cody Jul 05 '13 at 12:42
  • use NSApplicationWillTerminateNotification in name – Parag Bafna Jul 05 '13 at 12:50
  • tried atexit(), it complains in runtime about an identifier. – Wingston Sharon Jul 06 '13 at 06:42
  • @WingstonSharon: Please be more specific. What do you mean by “it complains in runtime about an identifier”? – Peter Hosey Jul 06 '13 at 23:02
  • Basically the function that i give in arguments to atexit(). (functionName) for example, even though that function is defined in the class, it gives me an error invalid identifier. self.functionName also doesnt seem to help. Neither does making functionName a class method and giving class.functionName. – Wingston Sharon Jul 07 '13 at 05:08
  • @WingstonSharon: Functions aren't part of classes. Are you sure you didn't define a method instead? You can only pass a function, not a method, to `atexit`. – Peter Hosey Jul 07 '13 at 07:12
  • in my class.h file `+ (void) test;` is what i'm using to declare it. changing the plus to a minus. i think i'm confused. is that a method or a function? if that's a method, how do i declare a function then? and how do i not make it part of a class? – Wingston Sharon Jul 07 '13 at 11:47
  • @WingstonSharon `+ (void)methodName` declares a class method (the equivalent of ie. `public static void methodName()` in Java), `- (void)methodName` declares an instance method – tttthomasssss Jul 07 '13 at 17:59
  • @WingstonSharon: Functions come from C, so you declare a function the same way you would in pure C. `atexit` requires one that takes no arguments and returns nothing, so it should be `void myFunction(void)`. There's also a block-based version, `atexit_b`. (That said, `applicationWillTerminate:` really is the right way to do this, unless you specifically need to do something—like delete a lock file or something—on *any* kind of exit. Normally, you shouldn't worry about it.) – Peter Hosey Jul 08 '13 at 01:26
  • You mentioned that “it says something on name: being an undeclared identifier when it is clearly on the .h & .m file before the function.” What do you mean by the latter half of that sentence? – Peter Hosey Jul 08 '13 at 01:26
  • oh yeah. there the `BeCalledOnExit` (from the first example in my question) is an instance method declared (with `-(void)`) in the class's.h file and has an implementation in the class's.m file. and yet that bit of code give an error that the function `BeCalledOnExit` is an undeclared identifier (even `self. BeCalledOnExit`). but the answer i accepted works fine for without me having to set up a notification observer with the above example code. – Wingston Sharon Jul 08 '13 at 06:15
  • @PeterHosey, so if i want to declare a function that `atexit()` will accept, do i have to declare a function like `void onExit(void){...}` outside the @implementation block of the class? – Wingston Sharon Jul 08 '13 at 06:17
  • @WingstonSharon: Yes. But, again, you almost certainly should just implement `applicationWillTerminate:` instead. – Peter Hosey Jul 08 '13 at 07:04
  • You can't refer to a method by just a name. You can use the method's selector (which would still need to be wrapped in an `@selector` literal), but you're already doing that in a different argument. The `name:` argument needs to be the name of the notification you intend to observe for, as an NSString. For your purpose, that would be `NSApplicationWillTerminate`. Even then, that's unnecessary if the observer is the application's delegate, since that object receives an `applicationWillTerminate:` message anyway. – Peter Hosey Jul 08 '13 at 07:10

4 Answers4

6

Implement - (void)applicationWillTerminate:(NSNotification *)notification on your AppDelegate and it will be called just before the application will terminate

So the Implementation of your AppDelegate could look something like:

@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    NSLog(@"I FINISHED LAUNCHING!");
}

- (void)applicationWillTerminate:(NSNotification *)notification
{
    NSLog(@"I WILL TERMINATE NOW!!!");
}
@end
tttthomasssss
  • 5,852
  • 3
  • 32
  • 41
  • So that works if i quit the application with `[[NSApplication sharedApplication] terminate:nil]` on a status menu item. But if just click the stop button in Xcode / terminate the process via activity monitor it doesn't work. – Wingston Sharon Jul 06 '13 at 06:40
  • 3
    The `applicationWillTerminate` notification is only sent when the application is quit the "normal" way, the ways you describe send something like SIGTERM or SIGKILL to your app, which is not the planned way to quit an application. But I think you can implement some signal handling for that, maybe the answer to this post is of help: http://stackoverflow.com/questions/8100944/catch-app-terminate-from-launchdeamon – tttthomasssss Jul 06 '13 at 19:46
  • i think that (-finalize) was depreciated in v10.8 (according to the docs). Anyway thanks for the link, i'll work on trying to catch SIGTERM somehow. – Wingston Sharon Jul 07 '13 at 05:11
  • @WingstonSharon: `finalize` was indeed deprecated, but that has nothing to do with termination. Terminate, finalize, and close are all three different things. – Peter Hosey Jul 08 '13 at 01:27
0

Your App Delegate should implement the - (void)applicationWillTerminate:(NSNotification *)notification to get the notification

(OR)

You can implement applicationShouldTerminate and perform clean of your files and return appropriate NSApplicationTerminateReply if your clean up fails

Srinidhi
  • 719
  • 5
  • 8
0

If you want to use a notification, you should be observing NSApplicationWillTerminateNotification.

Wain
  • 118,658
  • 15
  • 128
  • 151
0
NSApplication *app = [NSApplication sharedApplication];
[[NSNotificationCenter defaultCenter]
 addObserver:self
 selector:@selector(applicationWillTerminate:)
 name: NSApplicationWillTerminateNotification object:app];  
/*A notification named NSApplicationWillTerminateNotification.*/
- (void)applicationWillTerminate:(NSNotification *)notification
{

}
Parag Bafna
  • 22,812
  • 8
  • 71
  • 144