Reputation: 71852
I have app which uses firebase for database and I want to clear specific user field called current_venue
when user kill the app and for that I am using AppDelegate
method applicationWillTerminate
and it's actually calling when I kill the app but not completely.
Below is my code in AppDelegate
:
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
WebServiceAPI.checkOutVenue()
}
And another method is:
static func checkOutVenue() {
WebServiceAPI.sharedInstance.current_venue = ""
if WebServiceAPI.sharedInstance.user == nil {
return
}
let user = WebServiceAPI.sharedInstance.user!
let ref = FIRDatabase.database().reference()
ref.child("Clients").child(user.uid).child("current_venue").setValue("") { (err, venueIdRef) in
if err == nil {
WebServiceAPI.sharedInstance.current_venue = ""
}
}
}
And I tried to debug it something like below image:
When I kill app breakpoint 1 and 2 is calling but its never reaching at breakpoint 3.
I read the documentation from:
https://developer.apple.com/reference/uikit/uiapplicationdelegate/1623111-applicationwillterminate
Which says:
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.
And Actually its not taking more than 5 seconds to clear that field from firebase.
Same code is working fine when I open the app.
So my code is working fine but there is something which I am missing when I am killing the app.
Thanks for your help.
Upvotes: 1
Views: 1425
Reputation: 599956
A better way to ensure data is cleaned up when the user disconnects is to use onDisconnect
handlers. The Firebase documentation explains them, but here's a simple example of how you'd use it:
ref.child("Clients")
.child(user.uid)
.child("current_venue")
.onDisconnectRemoveValue()
When this code executes, the instruction is sent to the server to remove the node when the client disconnects. That means that it will always run, even when the client (or even the phone) crashes and your client-side code never gets a chance to execute.
Upvotes: 4
Reputation: 1056
Having an async task in applicationWillTerminat is not the best approach, because you have 5 sec to make sure that an async task depending on the strength of the internet connection should finish its execution (for you this maybe take less than 5 sec for a normal user this could take more) , otherwise the process will get killed.
As i mentioned in the comment section there is another case you didn't think about even if you get this work :
if user switch app to background at first, and after this try terminate app, applicationWillTerminate will not called.
you are trying something which is theoretically impossible
Try to think about something like this:
func applicationDidEnterBackground(_ application: UIApplication) {
WebServiceAPI.checkOutVenue()
}
Upvotes: 2