I am using socket.io client in swift.
Library: https://github.com/nuclearace/Socket.IO-Client-Swift
You know in ios when an app goes to background, probably everything is switching to suspended mode. When my app goes to background then comes to foreground after 2 minutes, this library is not connecting to server immediately. I think I have to close socket connection when app goes to background then I have to reconnect when comes to foreground.
To do this I used this methods:
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.
socket.reconnect()
}
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.
socket.close()
}
But not worked. When app comes to foreground I completely disconnected from server.
I know this is a difficult problem to resolve. But I guessed someone using this library in Stackoverflow.
How can I handle this situtation?
Related
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
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 applicationWillEnterForeground and in the applicationWillTerminate.
If the next time that your application(_:willFinishLaunchingWithOptions:) 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(_:didFinishLaunchingWithOptions:)
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.
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
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.
I am developing an app that's reading a db from parse.com with coordinates plotting out on a MapKit-map. Everything works fine but when a new pin is added manually by me on the web at parse.com, it doesn't show up when opening the app after pushing the home-button on my phone.
Where and how could I ask if the app has been shot down?
Hope I explained in an understandable way.
It could also be nice to have the app opening from scratch every time it is opened with the launch-image and so on. But I suppose that is not possible as one always has to close apps that are in the background by double-clicking on the phone.
Thankful for answers
If by 'app has been shot down' you mean the app moved to background after pressing the home button, then to know about this event you need to implement applicationDidEnterBackground: method in your appdelegate.m
These functions along with comments are created by xcode, when you start a new project.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(#"App 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.
*/
}
To know when the app was opened again, implement applicationDidBecomeActive: method in your appdelegate.m
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(#"App Active");
/* 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.
*/
}