NSInteger losing value when saved in NSUserDefaults - ios

When the following code executes, it logs "0" even though the indexPath.row selected is "1".
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSInteger location = indexPath.row;
[userDefaults setInteger:location forKey:#"savedlocations"];
NSInteger location2 = [userDefaults integerForKey:#"savedlocation"];
NSLog(#"l: %ld", location);

You've got several things that need to be fixed:
You're saving with the key savedlocations, but retrieving it with savedlocation. Note that the first is plural.
You're logging location, not location2, which is what's being pulled from NSUserDefaults. location2 will always be 0, because of the point above.
Edit: I had a third point here about calling synchronize, but it turns out that that is irrelevant to this situation, as explained by rmaddy in the comments below.
Other than those quick fixes, though, your configuration ought to work.

You are looking for the key "savedlocation" instead of "savedlocations".
EDIT:
0 is being returned by the method, which is what is returned for an NSInteger that can't be found. My bad on the weird wording.

Related

NSNotFound not working with NSUser default

As I am storing one Integer value into NSUserDefaults aas its used at many places. At first time its working fine but while i close my application and again open it I am check that user already selected any option in past feom NSUserDefaults stored value but I am failed in that
Some thing is wrong in my case
Here is my code for checking Integer value is there in userdefault :
NSInteger selectedBusinessUnit = [[NSUserDefaults standardUserDefaults] integerForKey:#"selectedUnit"];
if ( selectedBusinessUnit != NSNotFound){
//go to direct main screen.
}else {
// load Business unit screen for selection.
}
But its always found value even i am deleting app and reinastall it.
Always my selected value is 0.
Let me know what is my silly mistake here.
Edit:
[[NSUserDefaults standardUserDefaults] setInteger:sender.tag forKey:#"selectedUnit"];
[[NSUserDefaults standardUserDefaults] synchronize];
THNAKS .
Obviously there is a misunderstanding: NSNotFound is not equal to key is missing, it's a valid integer value.
The easiest way to keep your logic is to register the key-value pair with NSNotFound as the default value.
As soon as possible (applicationDidFinishLaunching or earlier) write
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *defaultValues = #{#"selectedUnit": #(NSNotFound)};
[defaults registerDefaults:defaultValues];
That means NSNotFound is considered as default value until it's overwritten the first time. The 3 lines must be executed every time the application launches. If the app is reinstalled the default value is taken again.
Now you can use your logic in the question.
PS: You don't need to synchronize after writing. The framework does that periodically.
The default value for integer is 0, according to the documentation:
-integerForKey: is equivalent to -objectForKey:, except that it converts the returned value to an NSInteger. If the value is an
NSNumber, the result of -integerValue will be returned. If the value
is an NSString, it will be converted to NSInteger if possible. If the
value is a boolean, it will be converted to either 1 for YES or 0 for
NO. If the value is absent or can't be converted to an integer, 0 will
be returned.
if you want to check if a key exists in NSUserDefaults use:
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"selectedUnit"] != nil)
{
...
}
NSUserDefaults storage only object, NSNumbers.
I think the problem in conversion from NSNumber, which you stored to integer in method integerForKey.
Another case - may be you forgot a synchronize NSUserDefaults.
You can set object like
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:#(yourIntegerValue) forKey:#"yourIntegerKey"];
[userDefaults synchronize];
and you can check like this
NSNumber *integerValue = [userDefaults objectForKey:#"yourIntegerKey"];
if (integerValue) {
//
}

Finding recurring items in NSUserDefaults

I am having a hard time understanding how to go about finding the values that repeat more than once. I'm just not understanding from the code below how to go about getting the duplicate values. thanks for any help!!
[appDelegate.scannedNumbers addObject:result];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:appDelegate.scannedNumbers forKey:#"scannedNumbers"];
[userDefaults synchronize];
[BT_debugger showIt:self message:[NSString stringWithFormat:#"After writing scannedNumbers: %#" [[NSUserDefaults standardUserDefaults] objectForKey:#"scannedNumbers"]]];
Setting a default has no effect on the value returned by the objectForKey: method if the same key exists in a domain that precedes the application domain in the search list.
Apple Documentation
You have to check if the key already exists before you will set another object for the same key.

Saving a location Array to NSUserDefaults

I'm attempting to build an app which will track a route, then store the route in parse.com so I can overlay the route taken by a user using MKpolyline.
I'm very new to Objective-c and IOS development, so please excuse my ignorance!!
I'm stuck when I try to save the route taken, then send/save the location array so I can rebuild the MKpolyline on the next view controller which is opened when the user completes the activity.
I'm not sure whether to save the location array to NSUserDefaults or save it to core data. At the moment I am converting the Array to an NSValue and the saving it to NSUserDefaults like so:
count = [self.locations count];
CLLocationCoordinate2D coordinates[count];
for (NSInteger i = 0; i < count; i++) {
coordinates[i] = [(CLLocation *)self.locations[i] coordinate];
NSValue *locationValue = [NSValue valueWithMKCoordinate:coordinates[i]];
[_locationsArray addObject:locationValue];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:totalDistance forKey:#"totalDistance"];
[defaults setObject:_locationsArray forKey:#"mapOverlay"];
// [defaults setDouble:_totalTime forKey:#"totalTime"];
[defaults setObject:avgSpeedToBeSaved forKey:#"averageSpeed"];
[defaults setObject:totalCalories forKey:#"totalCalories"];
[defaults synchronize];
Is this the right way to do this? And how do I rebuild the locations Array.
If anyone could point me in the right direction it would be greatly appreciated.
I've now changed my code to what was suggested by manecosta to rebuild the CLLocationCoordinates to create an MKPolyline, but my issue now is that the array is Null from where I start to convert into an NSValue. I am unable to figure out why this is, is there something wrong with the way I'm building LocationsArray in the first place?
Yes, I guess you're doing it right and to rebuild just do the opposite, which should be something like:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *locationsArray = [defaults objectForKey:#"mapOverlay"];
CLLocationCoordinate2D coordinates[[locationsArray count]];
NSInteger i = 0;
for(NSValue *locationValue in locationsArray){
coordinates[i] = [locationValue MKCoordinateValue];
i++;
}
About the fact that you're using User Defaults to store tons of data. I don't really know what is correct, but I'll tell you that I've previously used it to store the cache of my app which were quite big arrays and dictionaries and it never failed me.
You can get object from NSUserDefaults by using objectForKey:
As you have [defaults setObject:totalDistance forKey:#"totalDistance"];.
Now if you want to get the totalDistance back from the NSUserDefaults` then you can use following code:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *arrayLocation = [defaults objectForKey:#"totalDistance"];
But a piece of advise for you is not to use NSUserDefaults for your project. NSUserDefaults should only be used to store little amount of data (It's just a personal opinion.). Your locationArray is going to be quite large. Right?
A nice comparison between the two options NSUserDefaults & CoreData
What are the limitations of NSUserDefaults?
I'm posting answer here (from above link - in case the question gets unavailable in future time - who knows !!)
NSUserDefaults offers a trivial learning curve and thread safe
implementation.
Otherwise I've found Core Data superior in every way. Especially with
regards to configuring default values and migration routines.
EDIT: I actually haven't tried but it seems to be this way..
Tell me if it does not work.
To get back NSArray from NSValue
NSValue *value = [defaults objectForKey:#"mapOverlay"];
NSArray *arrayTemp;
[value getValue:&arrayTemp];

NSDictionary: validationhash fails to validate (Secure-NSUserDefaults)

I am using this helper class: Secure-NSUserDefaults
I'm running into a problem where the validationhash differs from the stored hash for a NSDictionary when I modify the latter and try saving it again.
Here is my code:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL valid = NO;
NSDictionary * modDict = [defaults secureDictionaryForKey:aKey valid:&valid];
if (!valid) {
//handle
}
for (NSString * modKey in modDict) {
NSMutableArray * modArray = [[modDict objectForKey:modKey] mutableCopy];
NSString * newValue = #"newValue";
[modArray replaceObjectAtIndex:0 withObject:newValue];
NSMutableDictionary *newModDict = [modDict mutableCopy];
[newModDict setObject:modArray forKey:modKey];
[defaults setSecureObject:newModDict forKey:aKey];
[defaults synchronize];
}
When I run this code once, kill the app, and start it again, all works as it should, and the validationhash matches. It always matches correctly on the first run, in fact. In other words: my code saves out the secure dictionary and the hash matches on the subsequent app run just fine (once).
BUT - if I run the same code a second time without killing the app between runs, the validationhash is different, and the &valid check fails.
I was able to trace down the problem to this line:
[newModDict setObject:modArray forKey:modKey];
If I comment it out, it works fine all the time, but then of course, the modification I am trying to make isn't made at all, I simply copy the Dictionary "as is".
I'm struggling to figure out what I am doing wrong or how to modify and re-save the NSDictionary so that the hash matches.
Thanks in advance for any help!
LOL! Funny how sometimes writing down a question in a concise way triggers new ideas. It just occurred to me what I had to do, and just now solved it like this:
[newModDict setObject:[modArray copy] forKey:modKey];
i.e. I had to make the edited NSArray non-mutable first.
Maybe someone will benefit from the answer. I'm too embarrassed to mention how long I worked on this last night.

NSUser default is not saving any value

I am trying to store userid coming from server to userDefaults which is a NSUserDefault object, but its always showing 0 for the value of userDefaults, I had tried using setObject method too but still its not working, and i have checked for informatioon coming from server its never a 0. value for user id is never 0 but still NSUserDefault is showin a 0 for it.
int userid=[[userdata objectForKey:#"id"] integerValue];
[userDefaults setInteger:userid forKey:#"UserID "];
[userDefaults synchronize];
NSLog(#"UID: %d",[[NSUserDefaults standardUserDefaults] integerForKey:#"UserID"]);
please help me thanks.
You are saving using the key #"UserId " note the space and reading using the key #"UserId" without an extra space.
As David Rönnqvist pointed out, you have a space in one of your keys but not in the other.
What I usually do is to #define all my user defaults keys in a file constants.h, and then use those constants instead of re-typing the string literal each time. This makes mistakes like yours impossible, and also makes it easier to keep track of the keys you are using.
you can try this way to store and retrieve data..
for set the value..
[[NSUserDefaults standardUserDefaults]setInteger:10 forKey:#"USERID"];
for retrieve the value..
NSLog(#"%d",[[[NSUserDefaults standardUserDefaults] valueForKey:#"USERID"]integerValue]);
good luck..
You can try this way
int userid=[[userdata objectForKey:#"id"] integerValue];
[userDefaults setInteger:userid forKey:#"UserID"];
[userDefaults synchronize];
NSLog(#"UID: %d",[[NSUserDefaults standardUserDefaults] integerForKey:#"UserID"]);
Happy coding........

Resources