Detect Unexpected Closing of My application - ios

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 ?

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.

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.

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{ }

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.

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.

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.

You can do this by listening to UIApplicationWillResignActiveNotification notification.
Detect when home button is pressed iOS

In the Application Delegate, you can check for different events. Check for applicationWillResignActive method or ApplicationDidEnterBackground.
The appropriate location will depend on your usecase.

Related

How can I handle my app when user lock device in application [duplicate]

This question already has answers here:
Detect iOS app entering background
(7 answers)
Closed 5 years ago.
I'm using XMPPframework for my application to get messages the problem is when user lock device when app is running and then unlock again the XMPPStream is disconnected from server and become useless but not when user just press home button (when user came to application again, XMPP starts reconnecting which is fine!) I searched the net and I found that this method are called before device get locked:
func applicationWillResignActive(_ application: UIApplication) {
print("i am in will resign")
// 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 invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
print("i am in background")
// 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.
}
I want to implement this method and also didbecomeactive method in my viewcontroller which user locked device in I simply put this on my vc but didn't work out:
class ViewController: x ,UIApplicationDelegate {
func applicationWillResignActive(_ application: UIApplication) {
print("frommmm vc i am in will resign")
}
}
I know it because I didn't give delegate to vc but how can I do this or what else can I do for my problem?
Thanks in Advance
you can not just add the UIApplicationDelegate to a any view to get it called.
use the methods defined in the protocol UIApplicationDelegate in your AppDelegate.swift
PS:
if you like to get informed deep in your views then you have to follow the suggestions in Detect iOS app entering background

Can I call a function to cal a server in iOS applicationWillTerminate?

I, I want notify to my server when my iOS objective c application is closed by a user, and I want add a call into my applicationWillTerminate delegate function. 
But I don't know if it is possible, because I have added a UILocalNotification and it isn't showed...
Could I call my server when the user close the app?
This method is rarely called and not reliable but why not to save some settings on these methods
- (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)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
so that when you open the app again you check these values and call the service you wanted

What method of AppDelegate will be called after entering into Suspended state?

My App goes in background, If I open again, It shows same page where I left it.
While, If iOS puts app into Suspended state, yet it is in memory. If I come back, which AppDelegate methods will be called.
Actually my purpose is to restore same screen from suspended to app, if it is not TERMINATED.
Last thing, Will didFinishLaunchWithOptions will be called if App is returning from SUSPENDED state.?
Thanks..
As Apple Documentation states,
application:willFinishLaunchingWithOptions:—This method is your app’s first chance to execute code at launch time.
application:didFinishLaunchingWithOptions:—This method allows you to perform any final initialization before your app is displayed to
the user.
applicationDidBecomeActive:—Lets your app know that it is about to become the foreground app. Use this method for any last minute
preparation.
applicationWillResignActive:—Lets you know that your app is transitioning away from being the foreground app. Use this method to
put your app into a quiescent state.
applicationDidEnterBackground:—Lets you know that your app is now running in the background and may be suspended at any time.
applicationWillEnterForeground:—Lets you know that your app is moving out of the background and back into the foreground, but that
it is not yet active.
applicationWillTerminate:—Lets you know that your app is being terminated. This method is not called if your app is suspended.
so applicationWillEnterForeground and applicationWillResignActive will be get called!
- (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 invalidate graphics rendering callbacks. 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)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
didFinishLaunchWithOptions didnt call.
Accoding to application's life cycle, Your app will not get any notification when ios will put your app in suspended mode. Whenever your app enters in background mode and if its not doing anything - not processing - ios will put it in suspended state.
But when suspended and its still in memory, You don't really need to do anything to display same screen where your app was before. ios automatically keep the state of app. You need to manage this only if your app is getting terminate while in suspended mode ..i.e. not in memory.
If you don't have any execution in background with any of background execution method , you can consider app in suspended mode if you receive notification for applicationDidEnterBackground store state of your app somewhere and applicationWillEnterForeground you can display app with stored state.
or if you are executing some finite task in background, You can keep local variable and use that for keeping track of suspended or now. on applicationDidEnterBackground, variable = inBackground, when you task completed and variable == inBackground, set variable == inSuspended and also store state of your app somewhere. on applicationWillEnterForeground
if variable == inSuspended
{
//Display app according to previously stored state.
`variable == inForgorund`,
}
You can test it your self using breakpoints in AppDelegate file.
If user will click on Home button once, app is in suspended state.
If user will click on Home button twice, app is in inactive state.
While user comes from suspended state to the app, I found following method calls.
first : applicationWillEnterForeground then applicationDidBecomeActive.
didFinishLaunchingWithOptions not called.
More details

when should i store and re-store to keychain on ios swift?

I see in the appDelegate few methods and I'm not sure if storing and re-storing user state in just some of them covers all scenarios?
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.
stopTasks()
setSharedPrefrences()
}
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.
stopTasks()
setSharedPrefrences()
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
startTasks()
getSharedPrefrences()
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
startTasks()
getSharedPrefrences()
connectGcmService(application)
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
stopTasks()
setSharedPrefrences()
disconnectGcmService(application)
}
should I store\restore in only some of them?
when should I disconnect and reconnect to GCM service?
are my restore redundant?
Keeping a local flag saying is restore has been made is not practical, as the application might destroy it?
Read about The App Lifecycle: Execution States for Apps in Apple's App Programming Guide for iOS.
Also, the documentation in UIApplicationDelegate for the methods you mention in your question contains very detailed information when they are called. Take the documentation for applicationWillResignActive as an example.
didEnterBackground is always preceded by willResignActive, so there is no need to run the same code.
willEnterForeground is always followed by didBecomeActive, but didBecomeActive can also be called in other situations (see below).
willResignActive can be called without didEnterBackground being called, e.g. a 10% battery warning or a phone call comes. If the user declines the call, your app will remain in the foreground and didBecomeActive is called next to tell you that the app is active again.
willTerminate is never called in modern iOS apps. It was used in iOS 2 and 3 before iOS supported multitasking. Since apps nowadays move to the background when the user "quits" them, this event is no longer used. (When the OS kills your app due to memory pressure while it is in the background, it gets killed right away without executing any more code.)
In summary:
stopTasks/startTasks should be in willResignActive and didBecomeActive.
Saving/restoring user data can be done in willResignActive/didBecomeActive or didEnterBackground/willEnterForeground. I would probably choose the latter.

When is applicationDidBecomeActive called?

When does the method applicationDidBecomeActive get called? What is the purpose of this method?
Understand the states and transitions of an iOS
States
Non-running - The app is not running.
Inactive - The app is running in the foreground, but not receiving events. An iOS app can be placed into an inactive state, for example, when a call or SMS message is received.
Active - The app is running in the foreground, and receiving events.
Background - The app is running in the background, and executing code.
Suspended - The app is in the background, but no code is being executed.
The seven most important application delegate methods
The operating system calls specific methods within the application delegate to facilitate transitioning to and from various states. The seven most important application delegate methods a developer should handle are:
application:willFinishLaunchingWithOptions
Method called when the launch process is initiated. This is the first opportunity to execute any code within the app.
application:didFinishLaunchingWithOptions
Method called when the launch process is nearly complete. Since this method is called is before any of the app's windows are displayed, it is the last opportunity to prepare the interface and make any final adjustments.
applicationDidBecomeActive
Once the application has become active, the application delegate will receive a callback notification message via the method applicationDidBecomeActive.
This method is also called each time the app returns to an active state from a previous switch to inactive from a resulting phone call or SMS.
applicationWillResignActive
There are several conditions that will spawn the applicationWillResignActive method. Each time a temporary event, such as a phone call, happens this method gets called. It is also important to note that "quitting" an iOS app does not terminate the processes, but rather moves the app to the background.
applicationDidEnterBackground
This method is called when an iOS app is running, but no longer in the foreground. In other words, the user interface is not currently being displayed. According to Apple's UIApplicationDelegate Protocol Reference, the app has approximately five seconds to perform tasks and return. If the method does not return within five seconds, the application is terminated.
applicationWillEnterForeground
This method is called as an app is preparing to move from the background to the foreground. The app, however, is not moved into an active state without the applicationDidBecomeActive method being called. This method gives a developer the opportunity to re-establish the settings of the previous running state before the app becomes active.
applicationWillTerminate
This method notifies your application delegate when a termination event has been triggered. Hitting the home button no longer quits the application. Force quitting the iOS app, or shutting down the device triggers the applicationWillTerminate method. This is the opportunity to save the application configuration, settings, and user preferences.
need additional information ref this link1 or apple link2
When a user is using an application he is in an active state. The user switch to inactive state from a resulting phone call or when a pull down notification center is pulled or when the home screen is pressed(This is when the app is told to be in background state) and then the app is opened again(This is when the app is told to be back to foreground state).
So every time the user switches from inactive state to active state
applicationDidBecomeActive this delegate is called

Resources