NSUserDefaults saves / loads on simulator but not on device - ios

I am doing an iphone game and saving data using NSUserDefaults. Here is how I save a user:
-(void) saveUser:(User*)user forPosition:(int) position{
NSData *myEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:user];
NSUserDefaults*savedData=[NSUserDefaults standardUserDefaults];
[savedData setValue:myEncodedObject forKey:[NSString stringWithFormat:#"user%i",position]];
[savedData synchronize];
self.currentUser=user;}
And here is how I load it:
-(BOOL) loadUser:(int) position{
if([savedData objectForKey:[NSString stringWithFormat:#"user%i",position]]){
NSData *encodedObject = [savedData objectForKey:[NSString stringWithFormat:#"user%i",position]];
User *user = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
self.currentUser=user;
return YES;
}
else return NO;}
As you can see, I am saving a custom class on NSUserDefaults. To do that I used guidance from How to store custom objects in NSUserDefaults (in case anyone is interested).
When I use this in the simulator it works perfectly. The problem is that if I run this on my iphone (iphone 6 on ios 8.1) it doesn't load anything.
Any ideas of what it could be? I've already visited this question NSUserdefaults works on Simulator but not on Device but nothing worked.
Thanks!

I guess there could be some problem saving it.
Check what exactly is being saved.
You can print the complete NSUserDefaults using this

Have you tried setObject instead of setValue ?
[savedData setObject:myEncodedObject forKey:[NSString stringWithFormat:#"user%i",position]];

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?

Intermittently Calling [NSUserDefaults synchronize] Returns Success but isn't shown during ObjectForKey

I have 2 applications sharing data via the NSUserDefaults, initWithSuite ID. Using iOS Dev Center.
One in 2 attempts the following code block apparently fails to write my dictionary object to the shared UserDefault area, I use the BOOL response from Synchronise to check the success. eg, (4 NSData objects, one, or more, or all of the items might fail to write to storage).
I use [[NSUUID uuid] UUIDString] as a key [EDIT: Been told in comments that this changes value?, Tried a Static String same result, 25% fail rate]
Any help will be greatly received.
Writer - Application 1
NSUserDefaults *myDefaults = [[NSUserDefaults alloc]
initWithSuiteName:FRGFileShareID];
NSString *uuid = [[NSUUID UUID] UUIDString];
[myDefaults setObject:**customObjectDict** forKey:uuid];
BOOL successSave = [myDefaults synchronize];
if (!successSave) {
DLog(#"Failed To Save To Defaults");
}
Reader - Application 2
NSUserDefaults *myDefaults = [[NSUserDefaults alloc] initWithSuiteName:FRGFileShareID];
if ([myDefaults objectForKey:uuid]) {
[mediaArray addObject:[myDefaults objectForKey:uuid]];
[myDefaults removeObjectForKey:uuid];
}
If i log out [[myDefaults dictionaryRepresentation] allKeys] im lucky if any of my keys are there.
Again with this working 75% of the time, im not sure whats causing the intermittency but its killing the usability of my feature.
You have not pass the value to NSUserDefault, change the code like this,
[myDefaults setObject:uuid forKey:"myDict Object"];
[myDefaults synchronize];

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.

Frank (Cucumber) - Detecting first run

I want to write a test that says if this is the first time the app is being launched, then directions should be displayed. How can i detect the first app launch with Frank? I was thinking use NSUserDefaults, but I still don't know how to do that. Example step definition code would be great. Thanks a lot.
Take advantage of the fact that an NSUserDefaults not previously set is nil:
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSNumber *firstRun = [userDefaults valueForKey:#"firstRun"];
if (firstRun == nil)
{
[userDefaults setValue:#YES forKey:#"firstRun"];
[userDefaults synchronize];
// Do what you want here
}

How to make the save data appear when loading view controller?

The following code is saving data and loading, but it doesn't show the data when loading view controller.It just says label (Xcode default uilabel).
I believe that I have to use synchronize ,but I am not too sure. May someone help me out.
Implementation file:
- (IBAction)minus
{
mini = mini - 1;
minus.text = [NSString stringWithFormat:#"%i", mini];
[[NSUserDefaults standardUserDefaults] setInteger:mini forKey:#"M"];
}
- (void)viewDidLoad
{
mini = [[NSUserDefaults standardUserDefaults] integerForKey:#"M"];
}
Header file:
IBOutlet UILabel *minus;
Change:
[[NSUserDefaults standardUserDefaults]setInteger:mini forKey:#"M"];
Into:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
[prefs setInteger:mini forKey:#"M"];
[prefs synchronize];
And it should work.
And i dont see you setting minus.text in viewdidload.
As H2CO3 says, you need to end the save process with
[prefs synchronize];
Why don't you open the iPhone Simulator folder to see if a plist file has been created inside Library > Preferences?

Resources