Clear data from NSUserDefaults when app kill - ios

Once I kill application then I want to Clear data from NSUserDefaults, but sometimes it is not getting cleared.
I have added the code into this method :
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
[[NSUserDefaults standardUserDefaults]removeObjectForKey:kcoupondic];
[[NSUserDefaults standardUserDefaults] synchronize];
}

Why are you using NSUserDefaults if you want to clear values on app termination.
Use global variable instead of NSUserDefaults
OR
If you wan't to remove all NSUserDefaults try this:
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];

applicationWillTerminate is not always called. This is from Apple's documentation.
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.
For apps that do not support background execution or are linked against iOS 3.x or earlier, this method is always called when the user quits the app. 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.
To answer your question as to why your data is not getting cleared, maybe this method is not getting called. Try and add some logs to check if the method gets called.
I would rather put this code in applicationDidFinishLaunchingWithOptions inside AppDelegate. In this case, you're sure that at every app launch you'll clear this data before you re-populate it.

For Swift:
if let bundleId = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: bundleId)
}
Here, we are optional unwrap bundleIdentifier to prevent crash.

Try writing your code to clear NSUserDefaults in applicationWillResignActive instead of applicationWillTerminate.

Related

Will NSUserDefaults remain if user quits app and are they global?

I'm using NSUserDefaults in my iOS app to record some specific info about the user's receipt state.
I'd like to confirm:
If the user quits the app, will those defaults remain?
Are they global, for example I'm currently using the following line to either get or set them and across different methods. I just want to be certain the data within it persists - so if I set in method1 then later method2 I use the same line to get, it will have whatever I set in method1:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
If the user quits the app, will those defaults remain?
Yes, they are persistent.
Are they global?
Global in the sense of your whole app: Yes.
Global in the sense of across apps: No. They are in the app's sandbox.
From the NSUserDefaults documentation (see https://developer.apple.com/documentation/foundation/nsuserdefaults?language=objc)
With the exception of managed devices in educational institutions, a user’s defaults are stored locally on a single device, and persisted for backup and restore. To synchronize preferences and other data across a user’s connected devices, use NSUbiquitousKeyValueStore instead.
So for your first question the answer is yes.
Accordind to your second question, doc says:
At runtime, you use NSUserDefaults objects to read the defaults that your app uses from a user’s defaults database. NSUserDefaults caches the information to avoid having to open the user’s defaults database each time you need a default value. When you set a default value, it’s changed synchronously within your process, and asynchronously to persistent storage and other processes.
And even so, it declares that the class is thread safe, so you can be sure about persistent results (for your second answer).
Additionally with #Nikolai Ruhe answer.
if I set in method1 then later method2 I use the same line to get, it will have whatever I set in method1: NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
The UserDefaults class is thread-safe.
Two further points.
The uselessness of synchronize has grown up gradually through versions of iOS. It used to be essential; then advisable; then unnecessary. I can’t give you an exact timeline but a lot of it depends on how far back in iOS you want your app to work.
If you try to test some of these things in Xcode, beware. Up to and including iOS 11, synchronize does not write all the way to disk, but only puts data in a “lazy write” queue. Pressing the Stop button in Xcode (or pressing Run and allowing Xcode to stop the previous running app automatically) shuts everything down abruptly, more abruptly than anything a user can do, and the lazy writes are not written out, but lost. This is confusing while you are resting!! I filed a report on it and was told by Apple that (as Microfot would put it) “This behaviour is by design”.
But just to be clear: that second point does not present a problem for real apps in a real environment, only when you are trying to test “save and restart” scenarios. Waiting 5-10 seconds seems to be long enough for the flushed data to make it all the way to disk.

save state when phone turned off

I created a saveState() method that uses UserDefaults to save certain settings at certain parts of my App. It works fine when I exit the App and return, but if I actually turn my (iOS) phone off, when I start the App again, the settings are not saved. In addition to those places where I call the saveState() method in the code, I also call saveState() in three AppDelegate functions: applicationWillResignActive, applicationDidEnterBackground and applicationWillTerminate. I have a loadState() function in viewDidLoad so any saved information will load at that time. Does anyone know what I am not doing re: saving/restoring settings when phone powered off?
When iphone off, AppDelegate's applicationWillTerminate
function Called when the application is about to terminate
how about use synchronize() after your saveState() called
In apple API https://developer.apple.com/reference/foundation/userdefaults/1414005-synchronize
Writes any modifications to the persistent domains to disk and updates all unmodified persistent domains to what is on disk.

iOS - How to guarantee that applicationWillTerminate will be executed

Is there A way to guarantee that the applicationWillTerminate method in the AppDelegate delegate will be hit? Something like a key in the info.plist file, etc..?
My goal: I'm working in a beacon app, the piece of code is in this article. My problem is that the message from the didEnterRegion keeps poping even when i'm beside the beacon. To solve that I'm setting a flag to control the message. My code below:
if(!UserDefaults.standard.bool(forKey: Constants.EnterZoneMsgShowName)){
let notification = UILocalNotification()
notification.alertBody = "Hi, you are about to arrive at CIDMA's office. Please open de demo app and turn on the bluetooth on your device to enrich your experience. "
UIApplication.shared.presentLocalNotificationNow(notification)
UserDefaults.standard.set(true, forKey: Constants.EnterZoneMsgShowName)
}
I want to set this flag to false when I close the app. I tried to put it at the applicationWillTerminate but this method is not hit every time.
I would like to know how to guarantee that this code will be hit or if there is a better place to put the code: UserDefaults.standard.set(false, forKey: Constants.EnterZoneMsgShowName)
applicationWillTerminate(_:) - Tells the delegate when the app is about
to terminate.
For apps that do not support background execution or are linked against iOS 3.x or earlier, this method is always called when the user quits the app.
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.
What you want to call is applicationDidEnterBackground if your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.

issue with NSUserDefaults (becomes null)

We are developing an iPhone application. The app is available in the app store. We are using NSUserDefaults to store our usertoken value. But some users reports that the usertoken is became null when the app idle (in background) for long time. But normally the value is getting.
The following is the code for storing usertoken in the NSUserDefaults. We are setting the value to the userToken from the login page and signup pages.
[[NSUserDefaults standardUserDefaults] setObject:userToken forKey:USER_TOEKN];
I have not called synchronize after setting value to NSUserDefaults. Could you please help
You need to call [[NSUserDefaults standardUserDefaults] synchronize]; if your app is going to be backgrounded - my guess is the app idles before the defaults automatically synchronizes. From the documentation:
Because this method is automatically invoked at periodic intervals, use this method only if you cannot wait for the automatic synchronization (for example, if your application is about to exit) or if you want to update the user defaults to what is on disk even though you have not made any changes.
As for where to do this, take a look at applicationWillResignActive: and applicationDidEnterBackground: in your Application Delegate.
Try something like this:
NSUserDefaults *udf = [NSUserDefaults standardUserDefaults];
[udf setObject:userToken forKey:USER_TOEKN];
[udf synchronize];
It will store your value permanently.

Persisting NSUserDefaults information between application terminations

In iOS4, when I save NSUserDefaults, the information gets saved. But then, if the application becomes inactive, and I kill the application (by double clicking the home button and then terminating the app), and launch the application again, the NSUserDefaults are not read.
Now, is this the default behaviour of NSUserDefaults that if the app is terminated due to any of the issues, the next launch will not store the information?
The call I am using to persist the info is:-
[[NSUserDefaults standardUserDefaults] registerDefaults:
[NSDictionary dictionaryWithObjectsAndKeys:
"Some date", #"Validity",
nil]];
after you register defaults add this
[[NSUserDefaults standardUserDefaults] synchronize];
until you synchoronize, the standardUserDefaults gives current/correct values as long as the app is alive.
once the app is terminated, since you didn't sync the standardUserDefaults, the app will read the unsynced values on the next launch.
Example: Think of it like a google doc that you are editing.
the AutoSave feature of google document is equivalent to the nsuserdefaults synchornize. If you close the browser before the changes you made to the document has been autosaved, the next time you load it up, you'll see the old content.
The call you mention to persist the user defaults, registerDefaults, does not actually persist anything to disk. What registerDefaults does is initialize the defaults to use for the application if it can't find any on the disk. You should do this on each application launch, typically in the initialize method for the app delegate.
Once your application is running it will typically modify the user defaults. Whenever you want to save these modified defaults to the disk you should call:
[[NSUserDefaults standardUserDefaults] synchronize];
After the defaults have been saved they will be loaded automatically on any subsequent application launches.

Resources