Adventures in Useless-but-Interesting iPhone Esoterica: UIApplicationMain() Function Never Returns

by Clint on August 5, 2009

Consider the following main() method which you’ll find in most iPhone applications:

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int retVal = UIApplicationMain(argc, argv, nil, nil);
    [pool release];
    return retVal;
}

You might assume (as I did) that when an iPhone application ends, the above call to UIApplicationMain() will return and the rest of main() will run, eventually returning an integer. That assumption would be incorrect, however.

UIApplicationMain() never actually gets a chance to finish, nor do any of the statements that follow it have a chance to execute. When an iPhone OS application is closed (e.g., the user pushes the home button) the application is given a few seconds to run its -applicationWillTerminate method and then it calls the exit() system function. This makes sense, if you think about it: it’s more efficient to just stop the program and let the operating system free up all of its memory at once instead of running several individual -dealloc statements. Dump the whole trash bin instead of picking stuff out one-by-one, so to speak.

However, when I noticed this several months ago (while trying to run some logging and shut-down statements in main) I was very confused; the official Apple documentation for the UIApplicationMain() function said zilch about UIApplicationMain() never returning. In fact, while all the iPhone documentation obviously encouraged putting shutdown code inside the standard -applicationWillTerminate method, it said nothing about the fact that it’s essentially pointless to write any code after your call to UIApplicationMain() (aside from the return statement, necessary to keep the compiler happy).

After some collective head-scratching on developer forums someone observed that the documentation for NSApplicationMain()–the AppKit/Cocoa counterpart to UIApplicationMain()–did describe the exit(0) behavior. This prompted me to fill out a quick bug report requesting that Apple update the documentation. Fast-forward to today, when I randomly came across that documentation and noticed that it has been updated and my bug was closed. Who knows if I’m actually the one responsible for instigating the correction, but I’ll tell myself that I am.

Clint Harris is an independent software consultant living in Brooklyn, New York. He can be contacted directly at ten.sirrahtnilc@tnilc.
  • Mike Orlov

    Nevertheless, there are situations when it returns. For example, if you are raising an exception in applicationDidFinishLaunching and intercepting it in main you are reaching this point. Of course it’s non-standard way to run, but it may be considered in development as test-case in order to carefully log what happens.


    int main(int argc, char *argv[])
    {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    int retVal = -1;
    @try
    {
    retVal = UIApplicationMain(argc, argv, nil, nil);
    }
    @catch(NSException* ex)
    {
    NSLog(@"Application terminates unexpectedly. The reason is ' %@ '.", ex.reason);
    }
    [pool release];
    return retVal;
    }

  • Bateramos

    Very cool stuff man… thanks a loot for this post, very useful.