views:

75

answers:

1

I'm attempting to implement custom termination behavior in a Cocoa application. Normally when my application exits gracefully, it performs final-runtime database cleanup and then exits. This occurs inside AppDelegate (delegate of NSApplication) whenever [NSApp terminate:aSender] is called:

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
    // database cleanup...
    return NSTerminateNow;
}

If an error occurs during runtime (e.g. the database file was deleted), I present the error to the user, and give them the option to Recover (put the file back and try again), or to Quit. If Quit is selected, I want to exit the app skipping database cleanup all-together since it's no longer possible. In essence, I'd like something like this:

- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
    BOOL gracefulTermination = ...;

    if (gracefulTermination == YES)
    {
        // Database cleanup....
    }

    return NSTerminateNow;
}

The problem, of course, is getting the value for gracefulTermination.

Is there a way to pass a custom variable to NSApp when terminate: is called, such as an infoDict, and then receive it inside applicationShouldTerminate:?

If not, is there a better way to accomplish custom termination behavior?


As far as I know, when terminate: is called by some other object, this happens:

  1. [NSApp terminate:self]; is called by foo (a.k.a. self).
  2. NSApp sends its delegate: [aDelegate applicationShouldTerminate:self]; (self is NSApp, not foo).
  3. aDelegate receives the message and executes applicationShouldTerminate: if implemented.

foo appears to disappear somewhere, and by the time aDelegate gets the message, it's gone for good and only NSApp appears as sender. This prevents me from passing an infoDict inside of foo, or just a plain infoDict, to aDelegate containing custom terminate: behavior.


I am aware that it's possible to exit without using [NSApp terminate:...] with something like exit(). Though from what I've read this is frowned down upon since it's not kosher for Cocoa. Plus it would also prevent any other cleanup operations from occurring inside applicationShouldTerminate:, operations which shouldn't be skipped even during a non-graceful exit.


Thanks in advance for any help and/or insight you have to offer! :)

+2  A: 

The ideal solution would be to structure your app in such a way that the app delegate can tell whether it's allowed to terminate.

Assuming it isn't possible for your application delegate to access this information any other way (say, which object triggered termination affects whether it can happen), this seems like the simplest solution: Subclass NSApplication, give it a terminationInfo property and override terminate: to set this property and call super.

Chuck
Thanks a lot Chuck. :) You got me thinking in the right direction. I ended up creating the 'gracefulTermination' variable inside AppDelegate. I can reach AppDelegate by using [NSApp delegate], call [appDelegate setGracefulTermination:NO], followed by [NSApp terminate:self]. When AppDelegate gets the applicationShouldTerminate: message, it'll know how to behave now.I'll mark your answer as correct within 24 hours unless someone else comes up with a better one. Thanks again!
Dave Gallagher