defaultPrefs not updating - ios

I have created a Prefs Controller class, which dose what it says controlls my prefs values. I have two specific values in my prefs both strings one that's called installSelected and the other called finishSelected, I setting them as a string that's either T or F...
When the app first starts I create the new prefs and the values are set to F automatically as those are their default values in the plist bundle. Then later in the app I overwrite installSelected to T. When I restart the application it returns the correct value as T. Then I write over it again using F. Again I restart but when I read the values this time it still shows T when it should be F.
I have debugged this and I am just not sure why it's not saving the value.
This is what my prefController method looks like that is used to write the new values:
- (void) writeBool:(NSString *)name MyBool:(NSString *)myboolString {
prefs = [NSUserDefaults standardUserDefaults];
if ([name isEqualToString:#"InstallsSelected"]) {
[prefs setObject:myboolString forKey:name];
}
else if ([name isEqualToString:#"FinishSelected"]) {
[prefs setObject:myboolString forKey:name];
}
[prefs synchronize];
}
I call the above method like this
[prefsController writeBool:#"InstallsSelected" MyBool:#"F"];
It just makes no sense that it's not working as I am able to change it from F to T but not back if needed and none of the code is different. What might be causing this problem?

Why are you using strings instead of bool values?
You have to set your boolean by using:
// Notice setBool
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"pref"];
and call synchronize after it:
[[NSUserDefaults standardUserDefaults] synchronize];
To retrieve the value, you call:
// Notice boolForKey
if(![[NSUserDefaults standardUserDefaults] boolForKey:#"pref"]) {
// False
} else {
// True
}
To register default prefs, use:
NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], #"pref1",
[NSNumber numberWithBool:YES], #"pref2",
nil];
NSUserDefaults * prefs = [NSUserDefaults standardUserDefaults];
[prefs registerDefaults:appDefaults];

Are you on the simulator or a real device? I have had serious problems getting the sync right in the Simulator. It turns out that if you just do a rebuild from xCode, the user preferences are not saved. They are saved if you bring the app to the background in the Simulator (press cmd-shift-H).
Also it helps to NSLog as much as possible to see what is written in the prefs.

Related

I cannot get NSUserDefaults to work, tried all i know, anyone had same issue?

I can't get NSUserDefaults to save a BOOL value. It's really simple and people do it but it just simply will not save. I tried everything I know. The most recent attempt being this:
if (_EndHide == YES) {
NSDictionary *aProperties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES]forKey:#"EndHide"];
BOOL boolValue;
if ([aProperties valueForKey:#"EndHide"])
boolValue = [[aProperties valueForKey:#"EndHide"] boolValue];
} else if (_EndHide == NO) {
NSDictionary *aProperties = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]forKey:#"EndHide"];
BOOL boolValue;
if ([aProperties valueForKey:#"EndHide"])
boolValue = [[aProperties valueForKey:#"EndHide"] boolValue];
}
What happens is I am making an iOS app game for iPhone and when you dodged these well objects for period of time, you end the game and unlock a button on the start menu named endless, after the story.
Now I need this button to be constantly unlocked. I managed to unlock it through a scene. It's all working but it just won't stay unlocked. Does anyone have any advice to help me with this?
Here is the endless button configuration and bool configuration:
#property(nonatomic, getter=isActive) bool EndHide;
#property(nonatomic) IBOutlet UIButton *endless;
That's all the code for the buttons and bools anyway to keep it unlocked.
I know it's simple but it won't work. Maybe a deep bug I tried it on another more updated version of Xcode but still to no avail. The issue is persistent and a real problem. I even tried switch saving that didnt work as well.
I cannot actually see any code that tries to save anything to the user defaults. You first need to get the user defaults object
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
To write a bool value:
[defaults setBool:YES forKey:#"EndHide"];
To read a bool value:
BOOL boolValue = [defaults boolForKey:#"EndHide"];
Fix any mistakes that I may have made yourself.
PS. Do NOT use valueForKey unless you really understand what it does. Use objectForKey or array syntax.
After days of searching, I found it. What happens is, instead of keep the bool changed aka always YES i just saved another bool with this:
in view did load top part:
if (_EndHide == YES) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"boolSet"];
} else if (_EndHide == NO) { }
so when the bool is yes you finished the game than this code:
in view did load top:
bottom:
if (![[NSUserDefaults standardUserDefaults] boolForKey:#"boolSet"]) {
NSLog(#"not workin -.-");
} else {
NSLog(#"finallyyyy workin !! YAeh");
_endless.hidden = NO;
}
code simply always remembers :D thank you everyone for trying to help me this method was best, endless is a button, create another bool that save in memory use it to unlock the button.
try this in the view did load
NSUserDefaults* prefs = [NSUserDefaults standardUserDefaults];
[prefs setObject:#"0" forKey:#"test"];
NSString * testValue = [prefs ObjectforKey:#"test"];
NSLog(testValue);
can you please tell me what is the console printing out?

Save and Load Data on Today Extensions (iOS 8)

Is it possible to save and load data on Today Extension using NSUserDefaults?
After closing the Notification Center, the widget behaves like an app which is terminated, so any data results lost. How could I solve this issue?
This is my code:
NSUserDefaults *defaults;
- (void)viewDidLoad {
[super viewDidLoad];
defaults = [NSUserDefaults standardUserDefaults];
NSArray *loadStrings = [defaults stringArrayForKey:#"savedStrings"];
if ([loadStrings objectAtIndex:0] != nil) {
[display setText:[NSString stringWithFormat:#"%#", [loadStrings objectAtIndex:0]]];
}
if ([loadStrings objectAtIndex:1] != nil) {
calculatorMemory = [NSString stringWithFormat:#"%#", [loadStrings objectAtIndex:1]].doubleValue;
}
}
- (IBAction)saveData:(id)sender {
NSString *displayString;
NSString *memoryString;
NSArray *saveStrings = [[NSArray alloc] initWithObjects: displayString, memoryString, nil];
defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:saveStrings forKey:#"savedStrings"];
[defaults synchronize];
}
You need to use app group identifier instead of com.*
For instance:
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"group.company.appgroup"];
Don't forget to synchronise when you store data
[shared synchronize];
You need to add the App Group stuff detailed under here and then if it actually worked (pretty iffy under beta) it should allow you to share NSUserDefault data like normal between the host and widget.
Edit: Normal NSUserDefaults does not work. Apple has implemented a new method. To use, simply redefine your NSUserDefaults instance like this:
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"com.you.app.container"];
For anyone wondering how in the world do you save and get values then look at this code.
In your regular app add this to save whatever you like in your *.m file.
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"group.yourcompanyname.TodayExtensionSharingDefaults"];
//save dic
[shared setObject:dictionary2 forKey:#"dicForTodayWidget"];
//save array
[shared setObject:tempArray2 forKey:#"arrayForTodayWidget"];
//save some value
[shared setObject:#"1234" forKey:#"myValForTodayWidget"];
[shared synchronize];
In your today widget under TodayViewController.m in viewDidLoad add this.
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"group.yourcompanyname.TodayExtensionSharingDefaults"];
//get dic
NSMutableDictionary *dictionary = [shared objectForKey:#"dicForTodayWidget"];
You first need the App Groups set up for both targets (application and the extension).
Then, use the
NSUserDefaults *shared = [[NSUserDefaults alloc]initWithSuiteName:#"group.company.myapp"];
to obtain the defaults object which you can read from/write to as usual.
If you want to be notified of changes to the defaults, use the NSUserDefaultsDidChangeNotification in your widget (or app).
For a step-by-step tutorial explaining all this, take a look at this blog post.
#edukulele
Today Extension and Main app run on two processes. Today Extension can't receive NSUserDefaultsDidChangeNotifications. I tried use MMWormhole. It is very good.

Store a value for the app's running time

I need to store a boolean value that would persist only for the app's running time. When the user quit the app (from the background as well) that variable should reset to default. How can I do this?
I tried constants. I keep constants in a separate .h file. In it I declared it like this.
const BOOL hasShownTutorial = NO;
And in the view controller,
if (hasShownTutorial == NO) {
[self showAppTutorial];
hasShownTutorial = YES;
}
I get an error at hasShownTutorial = YES; saying Read-only variable is not assignable.
I also tried going about this using NSUserDefaults. But the thing is the value is stored for good once you set it. Is there a way to clear it up when the app quits?
I'd appreciate your input and suggestions.
Thank you.
Store it in NSUserDefaults under a specific key.
[[NSUserDefaults standardDefaults] setBool:<myBool> forKey:#"myKey"];
Then to retrieve it later.
BOOL b = [[NSUserDefaults standardDefaults] boolForKey:#"myKey"];
If you want to clear the data.
NSString *domain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:domain];
For example, in your AppDelegate's implementation of -applicationWillTerminate:, just clear the data.
- (void)applicationWillTerminate:(UIApplication *)application
{
NSString *domain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:domain];
}
Edit: If the first method of clearing the data does not work, you can use the class method +resetStandardUserDefaults. For example the following would clear the current defaults.
[NSUserDefaults resetStandardUserDefaults];
A third possiblity is to specifically remove a property.
[[NSUserDefaults standardUserDefaults] removeObjectForKey:#"myKey"];
You can't change const value since it is a read only memory. Use static keyword instead.

NSUserDefault not able to retrieve value double

I'm creating a simple double value, saving it as NSUserDefault and trying to recover it...but it doesn't.
- (IBAction)try:(id)sender {
double value = 42.00;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setDouble:value forKey:#"kDoubleKey"];
// NSLog(#"loading %f",myDouble);
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSUserDefaults *fetchDefaults = [NSUserDefaults standardUserDefaults];
double intValue = [fetchDefaults doubleForKey:#"kDoubleKey"];
NSLog(#"douvle retrieve %f",intValue);
}
Do not forget to synchronise whenever you save something to the defaults:
put this at the end of your try method
[[NSUserDefaults standardUserDefaults]synchronize];
Here is what apple says about this: 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.

Detect when app is opened for the first time after launch

I want to display a help message on a view controller when the app is installed and opened for the very first time ONLY.
Is there a method I can use to do this?
You can display the help message once, and then store a boolean value in NSUserDefaults to indicate that it should not be shown again:
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
BOOL appHasBeenLaunchedBefore = [userDefaults boolForKey:#"HasBeenLaunched"];
if (!appHasBeenLaunchedBefore)
{
[self showHelpMessage];
}
[userDefaults setBool:YES forKey:"HasBeenLaunched"];
Use Grand Central Dispatch's dispatch_once() and check some persistent storage.
static dispatch_once_t pred;
dispatch_once(&pred,^{
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults];
BOOL hasLaunched = [userDefaults boolForKey:kAppHasLaunched];
if (!hasLaunched) {
[self showFirstLaunchMessage];
[userDefaults setBool:YES forKey:kAppHasLaunched];
}
});
This is the easiest way to ensure code only gets run once in your app per launch (in this case the block will only be executed once). More information about this is in the Grand Central Dispatch Reference. In this block you simply need to check some persistent storage, such as your preferences, to see if your app has ever launched before and display a message as appropriate.
Use a key in the user defaults. For example:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
BOOL launchedBefore = [userDefaults boolForKey:#"hasRunBefore"];
if(!hasRunBefore)
{
NSLog(#"this is my first run");
[userDefaults setBool:YES forKey:#"hasRunBefore"];
}
The user defaults are backed up by iTunes, so it'll normally be the user's first launch rather than the first launch per device.
EDIT: this is explicitly the same answer as e.James gave before me. The 'other answers have been posted' bar failed to appear. I'll leave it up for the example code but don't deserve credit fir a first answer.

Resources