11

Sometimes user presses the home button and close the application from recent list.

I want to warn user with a message like "This application not properly closed last time".

How to detect such unexpected closing of application? Is there any way to do it? Also i would like to save the data filled by user.

The below method works good but after staying in background for a while and closing the application will not get invoked to this method.

- (void)applicationWillTerminate:(UIApplication *)application

Is there any solution in swift 3.0 ?

Saranjith
  • 11,242
  • 5
  • 69
  • 122
  • 8
    There's no such thing as unexpectedly closing an app. It's normal for apps to be killed while in the background. Your app should properly handle this. It makes no sense to show the user such a message. – rmaddy Nov 30 '16 at 15:09
  • 1
    `I want to warn user with a message like "This application not properly closed last time".` - this is against Apple's way of doing stuff... Closing an app using the recent lists **is** the correct way to close an app on the iOS – Mihai Fratu Apr 05 '17 at 13:54
  • @MihaiFratu Yeah.. i agree with you but there is also another possibility of closing the app right.. how we can manage that too – Saranjith Apr 06 '17 at 05:54
  • The Apple way of doing things is that when you restart the app, the user shouldn't be able to distinguish between an app that is just returning from "paused state" and an app that is started from scratch. They won't let you pass the review if you add a dialog like that. – Sulthan Apr 07 '17 at 16:51

8 Answers8

5

To save the data filled by the user, you should use the func applicationDidEnterBackground(_ application: UIApplication) function.

This is the function description:

// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

As for "This application not properly closed last time" message you want to present the user - it's wrong to show such a message. The way to close the app is to press the home screen and close it from the list, so this is the expected behavior.

Witterquick
  • 6,048
  • 3
  • 26
  • 50
  • 4
    This should get accepted as it is the correct answer. Plus, it makes clear that *you should not do such a dialog*. Basically the philosophy on iOS in regards to why the app was closed is "That's none of your business". You need to "be prepared" for termination be it the result of the user (swipe it from the task manager) or the system. The entire life cycle is more complicated than often though. See https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html#//apple_ref/doc/uid/TP40007072-CH2-SW3 – Gero Apr 06 '17 at 07:43
  • 1
    Oh, one small addition: Don't just rely on the comments in the project template's app delegate. Those can become outdated or at least turn out to oversimplify things. The full documentation I linked as well as the proper method documentation explain this more clearly. Especially the comment in the `applicationWillTerminate` method is kind of misleading (it's basically still the same from the days before we had background execution and multitasking on iOS). – Gero Apr 06 '17 at 07:46
0

This method lets your app know that it is about to be terminated and purged from memory entirely. You should use this method to perform any final clean-up tasks for your app, such as freeing shared resources, saving user data, and invalidating timers. Your implementation of this method has approximately five seconds to perform any tasks and return. If the method does not return before time expires, the system may kill the process altogether.

-(void) applicationWillTerminate:(UIApplication *)application{    }
Prashant Ghimire
  • 518
  • 4
  • 20
  • It works well but after staying more time in background and closing from recent menu wont callling this method – Saranjith Nov 30 '16 at 12:25
0

You can use AppDelegate Method resignActive for saving data when user send app to background. And save a boolean value true in NSUserDefaults if it launches from didFinishLaunching method and check this boolean and saved data for computation in method didBecomeActive. Using data and boolean value you can show alert and reset both values.

Raushan Kumar
  • 171
  • 1
  • 2
  • 6
0

Please check this to understand how iOS application lifecycle works - https://developer.apple.com/library/content/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html

Now in your project find this following methods to track your app's lifecycle process.

For Objective-C

- (void)applicationWillResignActive:(UIApplication *)application{
      // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
     // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application{
     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillTerminate:(UIApplication *)application{
     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    // Saves changes in the application's managed object context before the application terminates.
}

For Swift(3.0)

func applicationWillResignActive(_ application: UIApplication) {        
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

func applicationDidEnterBackground(_ application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

func applicationWillTerminate(_ application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    // Saves changes in the application's managed object context before the application terminates.
}

Hope this helped.

onCompletion
  • 6,500
  • 4
  • 28
  • 37
-1

If the user kills the app manually while the app is not suspended, the applicationWillTerminate will be called in your app delegate.

When the user just press the home button the applicationDidEnterBackground is called in your app delegate.

If the applicationDidEnterBackground is called, and the applicationWillTerminate is not probably the app was not killed properly.

I said probably because there is no warranty that the applicationWillTerminate is called in case of app kill. In fact if the app is suspended the method will not be called.

For apps that support background execution, this method is generally not called when the user quits the app because the app simply moves to the background in that case. However, this method may be called in situations where the app is running in the background (not suspended) and the system needs to terminate it for some reason.

source: https://developer.apple.com/reference/uikit/uiapplicationdelegate/1623111-applicationwillterminate

The scenario when a manual kill would not cause this method to be called is when the user push the home button, and after a while he double press the home button and kill the app. In this scenario iOS would call applicationDidEnterBackground in your delegate when the user press the home button, and after ~5 seconds the app would get the status of suspended. When the user kills the app later on, its status would be suspended, and the willTerminate method would not be called.

the same happens if while suspended iOS kills the app to get resources giving to it the status of terminated.

What I would do is to persist the timeStamp of the applicationDidEnterBackground method call, cancel it on application​Will​Enter​Foreground and in the applicationWillTerminate.

If the next time that your application(_:​will​Finish​Launching​With​Options:​) gets called you have a value for the timestamp saved in the applicationDidEnterBackground it means that the user did not manually kill the app (maybe) and he did not come back after putting it in background.

If the user killed the app while the app was suspended, maybe in your case it would still be considered a misuse of the app, and the message can be displayed, so that all the use case are covered.

Giuseppe Lanza
  • 3,519
  • 1
  • 18
  • 40
-1

You shouldn't do that but if we are speaking about theory then the solution is to show the alert always except the first run.

I would save a boolean in UserDefaults, let's call it shouldShowWarning.

Everything else can go inside:

UIApplicationDelegate.application(_:​did​Finish​Launching​With​Options:​)

Inside the method you can check whether shouldShowWarning is true. If it's true, show the warning. Then set the value to true.

Now if the app is terminated and you return back, the alert will be shown.

If there is some scenario when you are terminating the app from code (which is very non-standard), just set shouldShowWarning to false to disable the warning when the app is restarted.

Sulthan
  • 128,090
  • 22
  • 218
  • 270
-2

You can do this by listening to UIApplicationWillResignActiveNotification notification.

Detect when home button is pressed iOS

Community
  • 1
  • 1
Abhijith
  • 3,094
  • 1
  • 33
  • 36
-3

In the Application Delegate, you can check for different events. Check for applicationWillResignActive method or ApplicationDidEnterBackground.

The appropriate location will depend on your usecase.

TheAppMentor
  • 1,091
  • 7
  • 14
  • i agree with you. but how i could know application was closed or not – Saranjith Nov 30 '16 at 11:46
  • Typically, when the user presses the home key, the front most application will move to the background and then to the suspended state. It does not get closed right away. My guess is that you are trying to save information each time the application goes to background. In that case, you can add your saving logic in the applicaitonWillResignActive. Also, to alert the user the next time, you can save a variable in the NSUserDefaults, check that value and alert the user if required. – TheAppMentor Nov 30 '16 at 11:50