Delete all keys from a NSUserDefaults dictionary iOS - ios

I use the NSUserDefaults dictionary to store basic information such as high scores etc so that when the user closes the app data is not lost. Anyways I use:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
to store data. If I wish to store a new high score for example then I would do:
[prefs setInteger:1023 forKey:#"highScore"];
[prefs synchronize]; //this is needed in case the app is closed.
and later if I wish to retrieve the high score I would do:
[prefs integerForKey:#"highScore"];
anyways the point is that I store a lot of other things because the NSUserDefaults enable you to store booleans, integers, objects etc. what method would I have to execute to delete all keys so that NSUserDefaults becomes like the fist time I launch the app?
I am looking for something like:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs deleteAllKeysAndObjectsInTheDictionary];
or maybe there is a way of getting all keys and I have to loop through each object but I don't know how to remove them.
EDIT:
I have tried :
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[NSUserDefaults resetStandardUserDefaults];
[prefs synchronize];
and I still am able to retrieve a high score....

If you have a look at the NSUserDefaults documentation you will see a method - (NSDictionary *) dictionaryRepresentation. Using this method on the standard user defaults, you can get a list of all keys in the user defaults. You can then use this to clear the user defaults:
- (void)resetDefaults {
NSUserDefaults * defs = [NSUserDefaults standardUserDefaults];
NSDictionary * dict = [defs dictionaryRepresentation];
for (id key in dict) {
[defs removeObjectForKey:key];
}
[defs synchronize];
}

Shortest way to do this with the same results like in Alex Nichol's top answer:
NSString *appDomain = NSBundle.mainBundle.bundleIdentifier;
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
[[NSUserDefaults standardUserDefaults] synchronize];

One-liner:
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:NSBundle.mainBundle.bundleIdentifier];

Simple Solution
Objective C:
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
Swift 3.0 to Swift 5.0 :
if let appDomain = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: appDomain)
}

Swift version:
if let bid = NSBundle.mainBundle().bundleIdentifier {
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(bid)
}

+ (void) resetStandardUserDefaults doesn't persist the changes, it simply resets the in-memory user defaults object so that the next synchronize call will read from the on-disk copy, instead of overwriting existing in-memory values with the on-disk versions.
Iterating over the keys is better, but there's actually a function that does this for you: removePersistentDomainForName:.
// you can usually get the domain via [[NSBundle mainBundle] bundleIdentifier]
[[NSUserDefaults standardUserDefaults]
removePersistentDomainForName:[[NSBundle mainBundle] bundleIdentifier]];
// or use a string for any other settings domains you use
//[[NSUserDefaults standardUserDefaults]
// removePersistentDomainForName:#"com.mycompany.myappname"];
[[NSUserDefaults standardUserDefaults] synchronize];
At the end of the synchronize operation, both the disk and memory copies of user defaults will contain none of the values set by your application.

Oneliner in Swift:
Swift 3
NSUserDefaults.standardUserDefaults().removePersistentDomainForName(
NSBundle.mainBundle().bundleIdentifier!)
Swift 4
UserDefaults.standard.removePersistentDomain(forName: Bundle.main.bundleIdentifier!)

For those of you that want to do this in the test target, use this (as the removePersistentDomain does not work for that case)
Swift 3:
for key in Array(UserDefaults.standard.dictionaryRepresentation().keys) {
UserDefaults.standard.removeObject(forKey: key)
}

For Swift 3:
let appDomain = Bundle.main.bundleIdentifier!
UserDefaults.standard.removePersistentDomain(forName: appDomain)

For Swift 3:
if let bundle = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: bundle)
}

I found it the most handy to place the code in an extension on UserDefaults.
Swift 5
extension UserDefaults {
static func clear() {
guard let domain = Bundle.main.bundleIdentifier else { return }
UserDefaults.standard.removePersistentDomain(forName: domain)
UserDefaults.standard.synchronize()
}
}
Usage
UserDefaults.clear()

Swift
place in your logic
if let appDomain = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: appDomain)
}

Swift
func resetUserDefaults(){
let userDefaults = NSUserDefaults.standardUserDefaults()
let dict = userDefaults.dictionaryRepresentation() as NSDictionary
for key in dict.allKeys {
userDefaults.removeObjectForKey(key as! String)
}
userDefaults.synchronize()
}

Does this method not do that:
+ (void)resetStandardUserDefaults
From the documentation for NSUserDefaults:
resetStandardUserDefaults
Synchronizes any changes made to the shared user defaults object and
releases it from memory.
+ (void)resetStandardUserDefaults
Discussion
A subsequent invocation of standardUserDefaults creates a new shared
user defaults object with the standard search list.
Based on this, you can do:
[NSUserDefaults resetStandardUserDefaults];
[NSUserDefaults standardUserDefaults];
and now the defaults should be reset.

Swift 3 or 4
We can even simplify described snippet into this modern expression:
func clearAll() {
let settingsDictionary = userDefaults.dictionaryRepresentation()
settingsDictionary.forEach { key, _ in userDefaults.removeObject(forKey: key) }
userDefaults.synchronize()
}

To remove all UserDefault value in swift (Latest syntax)
//remove UserDefaults
if let identifier = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: identifier)
UserDefaults.standard.synchronize()
}

In Swift 5.0 below single line of code is enough.
UserDefaults.standard.dictionaryRepresentation().keys.forEach(defaults.removeObject(forKey:))

I use this:
UserDefaults.standard.removeAll()

Related

UILabel text not being stored in NSUserDefault

I have a UILabel called 'labelA'. In this label is the letter 'A'.
When I am using NSUserDefault and start my app, the label is empty, but I don't know why?
Here is my ViewController.m file:
- (void)viewDidLoad {
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
self->labelA.text = [defaults objectForKey:#"labelAtext"]; }
- (void)defaults {
NSString *textLabelA = labelA.text;
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:textLabelA forKey:#"labelAtext"];
[defaults synchronize];
}
Here is my NSString in the ViewController.h file
NSString *textLabelA =#"A";
When i load my app without NSUserDefault the labelA.text = A.
does anybody know what's my problem. Thanks a lot :-)
Your method defaults is not being called anywhere, so the text value is never stored in NSUserDefaults.
[self defaults]; // This needs to be called somewhere before you try and access NSUserDefaults.
You should also be accessing self using dot notation, not ->
self.labelA.text = [defaults objectForKey:#"labelAText"];
-> is for dereferencing a struct in C, for more information - What is "->" in Objective C?
When you use UserDefaults. You should first test if you get a value as if the value doesnt exist you need to set it or not.
NSString * myPreference = #"labelAtext";
- (void)viewDidLoad {
NSUserDefaults* userDefault = [NSUserDefaults standardUserDefaults];
id labelValue = [userDefault objectForKey:myPreference];
if (labelValue) // if preference exist
self.labelA.text = labelValue; // set ur label
else
[self storeDefaultValue]; // you store a default value
}
- (void)storeDefaultValue
{
NSString *myDefaultValue = nil;
if ([self.labelA.text isNotEqualToString:#""]) // if ur label not empty
myDefaultValue = self.labelA.text;
else
myDefaultValue = #"Not Available"; // or whatever defaults value you want
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:myDefaultValue forKey:myPreference];
[defaults synchronize];
}
What do you really want to achieve as I don't really understand whats the point of storing a value in preference as soon as you load your app. Give more details on what is your goal.

NSUserDefaults Contains Value Or Not?

How to know whether NSUserDefaults contains any value?How to check whether its empty?
There isn't a way to check whether an object within NSUserDefaults is empty or not.
However, you can check whether a value for particular key is nil or not.
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSObject * object = [prefs objectForKey:#"your_particular_key"];
if(object != nil){
//object is there
}
NSUserDefaults *data = [NSUserDefaults standardUserDefaults];
NSString *string = [data objectForKey:#"yourKey"];
if(string==nil)
NSlog(#"nil")
Take a look at NSUserDefault documentation
// For saving the values
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
// saving an NSString
[userDefaults setObject:#"Ttest" forKey:#"key"];
// --- For Retrieving
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
// getting an NSString
NSString *myString = [userDefaults stringForKey:#"key"];
To check whether a specific value is set or not, no matter of its location (global or application's), check the returned value of -[NSUserDefaults objectForKey:]
id obj = [[NSUserDefaults standardUserDefaults] objectForKey:#"My-Key-Name"];
if (obj != nil) {...}
To check if the application (bundle) has any settings stored in user defaults:
NSUserDefaults* sdu = [NSUserDefaults standardUserDefaults];
NSString* bundleId = [[NSBundle mainBundle] bundleIdentifier];
NSDictionary* mainBundleSettings = [sdu persistentDomainForName:bundleId];
NSLog(#"%#", mainBundleSettings);
If you are interested in all possible values for which -[NSUserDefaults objectForKey:] will return something, including system global settings, simply call
NSDictionary* allPossibleSettings = [sdu dictionaryRepresentation];
NSUserDefaults is never empty. It combines global settings, bundle's settings, temporary data and maybe something else. For example, if you call:
[[NSUserDefaults standardUserDefaults] objectForKey:#"NSBoldSystemFont"]
you will get the #"LucidaGrande-Bold" string value which will be taken from global settings, even when your application has never set this value.

How to set initial values for NSUserDefault Keys?

I want to set some initial values for my NSUserDefault keys so that the first run of the app has some reasonable initial settings. I thought I ran across a simple way to do this in the app bundle .plist, but now I can't find it. Any ideas?
You should use the registerDefaults method of NSUserDefaults. Prepare a plist file in your bundle that contains the default preferences and then use that plist to register the defaults.
NSString *defaultPrefsFile = [[NSBundle mainBundle] pathForResource:#"defaultPrefs" ofType:#"plist"];
NSDictionary *defaultPreferences = [NSDictionary dictionaryWithContentsOfFile:defaultPrefsFile];
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultPreferences];
You have to execute this code on every launch of your app. It will add these values to a separate domain in the user defaults hierarchy. Whenever your app's user defaults don't provide a value for a certain key, NSUserDefaults will fall back to this domain and retrieve the value from there.
If you have many default values, let use ola's answer, otherwise this is good for a few params
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults boolForKey:USERDEFAULT_IS_INITIALIZED]) {
[defaults setBool:YES forKey:USERDEFAULT_IS_INITIALIZED];
// Set initial values
...
[defaults synchronize];
}
if ([[[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys] containsObject:#"initialValuesHaveBeenWritten"])
{
[[NSUserDefaults standardUserDefaults] setValue:obj1 forKey:key1];
[[NSUserDefaults standardUserDefaults] setValue:obj2 forKey:key2];
[[NSUserDefaults standardUserDefaults] setValue:obj1 forKey:#"initialValuesHaveBeenWritten"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
NB: Not tested, done from memory
-(void) loadDef
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
_removeAd=[userDefaults boolForKey:SAVE_AD_STATUS];
NSString* strDefSetting=[userDefaults stringForKey:SAVE_STATUS_ADSETTING];
if(strDefSetting==nil
||[strDefSetting isEqualToString:#""]
)
{
strDefSetting=#"0.5";
}
_floatAdmob=strDefSetting.floatValue;//0.5;
}

Sharing a NSString between two views

I need to share a string between two views in my application. When the user ends the game, the score is converted into a string. I then need to transfer that string into a different view controller where I display the score. I have a label set up and all but the view is not recognizing the string even though I am importing the header file from which the string is created. Any help would be great, thank.
This is my view controller where the string is created
NSString *scoreString = [NSString stringWithFormat:#"%d", score];
And this is where I try to display the string in a different view controller
- (void)viewDidLoad {
self.scoreString = score.text;
[super viewDidLoad];
}
For scores and similar data, you may want to use NSUserDefaults. These can be accessed at any time from any UIViewController. For example, you can implement methods similar to these to save and retrieve the data:
-(void)saveToUserDefaults:(NSString*)myString
{
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
if (standardUserDefaults) {
[standardUserDefaults setObject:myString forKey:#"Score"];
[standardUserDefaults synchronize];
}
}
-(NSString*)retrieveFromUserDefaults
{
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
NSString *val = nil;
if (standardUserDefaults)
val = [standardUserDefaults objectForKey:#"Score"];
return val;
}
NSUserDefaults also handles ints, BOOLs, NSArrays, etc. Check out the documentation or google around for examples.
You could use delegates or NSUserDefaults
Been asked similiar questions before:
Passing variables to different view controllers
How do I pass variables between view controllers?
EDIT
[[NSUserDefaults standardUserDefaults] setObject:#"STRING HERE" forKey:#"MyKey"];
and retrieve
[[NSUserDefaults standardUserDefaults] objectForKey:#"MyKey"];

Access an NSUserDefault from multiple views

I am trying to access an NSUserDefault called prefs from multiple views. I am allocating prefs in one view but I don't know how to access it without just reallocating a new NSUserDefault in the second view.
Also, my operating system is ios.
Here is my FlipSideViewController Function:
The function in my FlipSideViewController: 'NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
- (IBAction) changeRate:(id)sender {
if (rate.selectedSegmentIndex == 1){
[prefs setInteger:1 forKey:#"myRate"];//save
}
else if (rate.selectedSegmentIndex == 2){
[prefs setInteger:2 forKey:#"myRate"];//save
}
[[NSUserDefaults standardUserDefaults] synchronize];
};
And this is the MainViewController function:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
// [prefs setValue: #"0" forKey: #"myRate"];
if (!([prefs valueForKey: #"myRate"])){
[prefs setInteger:0 forKey: #"myRate"];
}
[prefs setInteger:2 forKey: #"myRate"];
int rateOption = [[prefs valueForKey: #"myRate"] intValue];
if (rateOption == 1)
{
dayOrHourly.text = #"% of Day:";
percentOrHours.hidden = YES;
hours.hidden = YES;
dayPercentage.hidden = NO;
}
else if (rateOption == 2)
{
dayOrHourly.text = #"# of Hours:";
percentOrHours.hidden = NO;
dayPercentage.hidden = YES;
}
Having more than one prefs for different views shouldn't be a problem. Just call
[prefObject synchronize];
when you modify one of the instances of NSUserDefaults in one view or try to access them from another view and you'll be fine.
But if you really want to keep a single object shared across all your view controllers, put it in your App Delegate. [I must say, I don't see the point...]
NSUserDefaults is a singleton class. You're not allocating instances of it, you're accessing it.
That said, have you tried using objectForKey instead of valueForKey? Values can't return values, (... valueForKey] intValue];) whereas objects do indeed return values.
Additionally, here's how I'd do it.
First, I'd define a constant in a global header, like so:
#define kSettings [NSUserDefaults standardUSerDefaults];
Then, you should be just fine accessing NSUserDefaults across views:
[kSettings setObject:#"This is a test." forKey:#"TestString"];
to read out the string, you would do this:
[kSettings objectForKey:#"TestString"];
I suggest defining some "global constants" for accessing objects stored in NSUserDefaults. For example:
#define kTestString [kSettings objectForKey:#"TestString"];

Resources