Ccna final exam - java, php, javascript, ios, cshap all in one. This is a collaboratively edited question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.
Sunday, June 10, 2012
Proper way to exit iPhone application?
I am programming an iPhone app, and I need to force it to exit due to certain user actions. After cleaning up memory the app allocated, what's the appropriate method to call to terminate the application?
On the iPhone there is no concept of quitting an app. The only action that should cause an app to quit is touching the Home button on the phone, and that's not something developers have access to.
According to Apple, your app should not terminate on its own. Since the user did not hit the Home button, any return to the Home screen gives the user the impression that your app crashed. This is confusing, non-standard behavior and should be avoided.
using the private interface : [UIApplication sharedApplication] will cause the app looking like it crashed, BUT it will call - (void)applicationWillTerminate:(UIApplication *)application before doing so; using exit(0); will also terminate the application, but it will look "normal" (the springboard's icons appears like expected, with the zoom out effect), BUT it won't call the - (void)applicationWillTerminate:(UIApplication *)application delegate method.
My advice:
Manually call the - (void)applicationWillTerminate:(UIApplication *)application on the delegate. Call exit(0);.
Go to your info.plist and check the key "Application does not run in background". This time when the user clicks the home button, the application exits completely.
My App has been rejected recently bc I've used an undocumented method. Literally:
"Unfortunately it cannot be added to the App Store because it is using a private API. Use of non-public APIs, which as outlined in the iPhone Developer Program License Agreement section 3.3.1 is prohibited:
"3.3.1 Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs."
The non-public API that is included in your application is terminateWithSuccess"
Which does all the work. And the best thing is, it is the useres intent to quit, which is why this should not be a problem calling it there.
On my Audio-App it was necessary to quit the app after people were syncing their device while the music was still playing. As soon as the syncing is complete I get a notification. But quitting the app right after that would actually look like a crash.
So instead I set a flag to REALLY quit the app on the next backgrounding action. Which is okay for refreshing the app after a sync.
In addition to the above, good, answer I just wanted to add, think about cleaning up your memory.
After your application exits, the iPhone OS will automatically clean up anything your application left behind, so freeing all memory manually can just increase the amount of time it takes your application to exit.
This has gotten a good answer but decided to expand a bit:
You can't get your application accepted to AppStore without reading Apple's iOS Human Interface Guidelines well. (they retain the right to reject you for doing anything against them) The section "Don't Quit Programmatically" http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices.html is an exact guideline in how you should treat in this case.
If you ever have a problem with Apple platform you can't easily find a solution for, consult HIG. It's possible Apple simply doesn't want you to do it and they usually (I'm not Apple so I can't guarantee always) do say so in their documentation.
Hm, you may 'have to' quit the application if, say, your application requires an internet connection. You could display an alert and then do something like this:
Have you tried exit(0)?
ReplyDeleteAlternatively, [[NSThread mainThread] exit], although I have not tried that it seems like the more appropriate solution.
On the iPhone there is no concept of quitting an app. The only action that should cause an app to quit is touching the Home button on the phone, and that's not something developers have access to.
ReplyDeleteAccording to Apple, your app should not terminate on its own. Since the user did not hit the Home button, any return to the Home screen gives the user the impression that your app crashed. This is confusing, non-standard behavior and should be avoided.
Its not really a way to quit the program, but a way to force people to quit.
ReplyDeleteUIAlertView *anAlert = [[UIAlertView alloc] initWithTitle:@"Hit Home Button to Exit" message:@"Tell em why they're quiting" delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[anAlert show];
After some tests, I can say the following:
ReplyDeleteusing the private interface : [UIApplication sharedApplication] will cause the app looking like it crashed, BUT it will call - (void)applicationWillTerminate:(UIApplication *)application before doing so;
using exit(0); will also terminate the application, but it will look "normal" (the springboard's icons appears like expected, with the zoom out effect), BUT it won't call the - (void)applicationWillTerminate:(UIApplication *)application delegate method.
My advice:
Manually call the - (void)applicationWillTerminate:(UIApplication *)application on the delegate.
Call exit(0);.
Check the QA here.
ReplyDeletehttp://developer.apple.com/iphone/library/qa/qa2008/qa1561.html
Go to your info.plist and check the key "Application does not run in background". This time when the user clicks the home button, the application exits completely.
ReplyDeleteMy App has been rejected recently bc I've used an undocumented method. Literally:
ReplyDelete"Unfortunately it cannot be added to the App Store because it is using a private API. Use of non-public APIs, which as outlined in the iPhone Developer Program License Agreement section 3.3.1 is prohibited:
"3.3.1 Applications may only use Documented APIs in the manner prescribed by Apple and must not use or call any private APIs."
The non-public API that is included in your application is terminateWithSuccess"
Your ApplicationDelegate gets notified of intentional quitting by the user:
ReplyDelete- (void)applicationWillResignActive:(UIApplication *)application {
When I get this notification I just call
exit(0);
Which does all the work. And the best thing is, it is the useres intent to quit, which is why this should not be a problem calling it there.
On my Audio-App it was necessary to quit the app after people were syncing their device while the music was still playing. As soon as the syncing is complete I get a notification. But quitting the app right after that would actually look like a crash.
So instead I set a flag to REALLY quit the app on the next backgrounding action. Which is okay for refreshing the app after a sync.
add UIApplicationExitsOnSuspend property on application-info.plist to true
ReplyDeleteIn addition to the above, good, answer I just wanted to add, think about cleaning up your memory.
ReplyDeleteAfter your application exits, the iPhone OS will automatically clean up anything your application left behind, so freeing all memory manually can just increase the amount of time it takes your application to exit.
This has gotten a good answer but decided to expand a bit:
ReplyDeleteYou can't get your application accepted to AppStore without reading Apple's iOS Human Interface Guidelines well. (they retain the right to reject you for doing anything against them) The section "Don't Quit Programmatically" http://developer.apple.com/library/ios/#DOCUMENTATION/UserExperience/Conceptual/MobileHIG/UEBestPractices/UEBestPractices.html
is an exact guideline in how you should treat in this case.
If you ever have a problem with Apple platform you can't easily find a solution for, consult HIG. It's possible Apple simply doesn't want you to do it and they usually (I'm not Apple so I can't guarantee always) do say so in their documentation.
Hm, you may 'have to' quit the application if, say, your application requires an internet connection. You could display an alert and then do something like this:
ReplyDeleteif ([[UIApplication sharedApplication] respondsToSelector:@selector(terminate)]) {
[[UIApplication sharedApplication] performSelector:@selector(terminate)];
} else {
kill(getpid(), SIGINT);
}
[[UIApplication sharedApplication] terminateWithSuccess];
ReplyDeleteIt worked fine and automatically calls
- (void)applicationWillTerminateUIApplication *)application delegate.
to remove compile time warning add this code
@interface UIApplication(MyExtras)
- (void)terminateWithSuccess;
@end