NSUserDefaults in iOS is randomly disappearing and reappearing - ios

Just wondering if anybody experience this issue?
I am developing an application in iOS using Objective-C at the moment.
Sometimes my data in NSUserDefaults will be missing after I compile the app.
But if I ignore it and recompile the app again the data suddenly reappears.
I already synchronized in several places (not in every key, but only in several places).
If anyone happened to face this issue before I hope you can share how to handle this issue.
P.S. I need a storage to save 1 particular object so I can retrieve it when the app reopens.
Edited to add the code
NSString *enPIN = [[NSString alloc]initWithString:[NSString stringWithFormat:#"%#", [enterField.text md5]]];
[[NSUserDefaults standardUserDefaults] setObject:enPIN forKey:#"pin"];
[[NSUserDefaults standardUserDefaults]synchronize];
NSLog(#"check pin %#", [[NSUserDefaults standardUserDefaults] objectForKey:#"pin"]);
The object is a string, i hash it using md5 and then store it in nsuserdefault, if it only randomly dissapearing maybe its not weird, but its also reapearing again after it dissapear if i recompile the apps

Check if your defaults are using only string value or bool or such.
If you are using any Object with Class (key and parameters) like NSObject to store in defaults I prefer you do the encoding and decoding accordingly before storing and retrieving the values.
Also If you storing any NSDictionary check if any of the object value inside that dictionary is not anything other than Bool, String , if there also any NSObject class or reference is stored then you may face same issue.
Refer this stackoverflow link as to how encode objects before storing to NSUserDefaults.
Lastly [defaults synchronise] call mandatory on viewwilldisappear or immediately after storing new value whichever way is your implementation.
Hope this helps.

I had a similar issue the other day with NSUserDefaults
Not quite sure what was causing it, but it was due to a bug in Xcode. I was able to fix the issue without changing my code at all. I simply cleaned the project (CMD-Shift-K) and restarted my computer, and then it worked just fine. It's worth a try
Are you getting any kind of error messages in the console?

Related

NSUserDefaults standardUserDefaults objects are being removed randomly

I am facing a very weird behavior for NSUserDefaults, the problem is that [NSUserDefaults standardUserDefaults] objects are being removed randomly!
My [NSUserDefaults standardUserDefaults] contains around 65 objects(60 small NSStrings and 3 arrays which the maximum count could be 4 and 2 other arrays with maximum count 30..notice that it has never been the maximum case when facing this problem) , one of these objects is a value checking if the user has already completed the registration phase.
When launching the application, sometimes this NSUserDefaults will contain only 5 objects from those 65 and the others are being removed from the plist without appearing again even if i relaunch the app., which lead the user to the registration phase again!!
i am pretty sure that i am using the save function correctly
[[NSUserDefaults standardUserDefaults] setObject:#"Value" forKey:#"Key"];
[[NSUserDefaults standardUserDefaults] synchronize];
i have searched google for similar behavior without finding anything that can help!
Does anyone faced such behavior and what is the solution to fix it?
Thank you for any help
I do want to help out here, since I have had exact same strange behavior with one of my projects.
So bear with me, what happened to my project is that: I had a singleton class, which encapsulates several properties, and I had overridden setters and getters for those properties. In a setter method, I get standardUserDefaults instance and set object for key, and synchronize. In a getter method, I return the object of the key. Also I have a login success indicator value to indicate if login is successful. And same as your issue, my objects disappear. After few days of struggle, it turns out that the login indicator got initialized to false when Network became unreachable. And in the indicator false clause, I was setting nil objects to user defaults.
My points are:
Double check if standardUserDefaults setObject:forKey: function calls are logically correct, make sure the objects are NOT nil when call
Check if you have logic (login, Network change etc) that invalidates the objects.
Run tests, find the minimal steps to replicate the issue. Use Debug session to examine the objects. (Give up believing in Random Disappearing)
Hope this gives a lead.

How can I protect integer data on NSUserDefaults from hacking?

I have the paid content on my application on App Store. And I save it using the following code:
paidContentCount = [[NSUserDefaults standardUserDefaults] integerForKey:#"paidContentCount"];
But it's easy to hack it. How can I protect integer data from hacking?
Never store such settings in NSUserDefaults! Use an iOS Keychain for it. Here is the wrapper, which makes the biggest part of work.
Besides it, you can read this article from Ray Wenderlich - there are a lot of good ideas of basic security.
You can try saving your content as string with [NSString hash] method, and after your app is loaded, compare paid content's hashes with value from NSUserDefaults
UPDATE: forgot that [NSString hash] returns NSInteger

NsmutableArray don't succeded to save at close of app

Hello I can not save locally where I have to save an array of strings, I add that this array must be saved when closing the application for iOS and the reopening needs to be recharged, I found thousands of guides online but none are very specific, someone says use NSUserDefaults others say to use NSCoding but in both cases i can not recharge these data can anyone help me?
To Save SMALL data - NSUserDefaults, NSCoding as suggested by other people or saving in plist also or else create a file in document directory and write the contents of array in that file.
LARGE Data- Save it in database using either sqlite or core data.
Choice depends on the requirement of the application and since you have not given the details of the data like maximum number of strings in the array, everyone can suggest you instead of telling a solution. Hope it helps :)
You can use NSUserDefaults:
[[NSUserDefaults standardUserDefaults] setObject:yourMutableArray forKey:#"Key"];
To get the value from NSMutableArray:
NSMutableArray *array = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"Key"]];
Hope this is helpful.

Save a value to disk XCode

I've got a pretty simple task that I'm trying to accomplish in Objective-C.
I make a call to a web site, and get a value from the web site through an HTTP call. I want to save this value to disk so I can retrieve it later.
What would be the best method to do this - a text file, or in the PList file?
It's just one value that may occasionally be updated. The call to the web site is made on-demand.
Consider using NSUserDefaults for storing single values
For Storing:
[[NSUserDefaults standardUserDefaults] setInteger:100 forKey:#"storageKey"];
For Retrieving:
NSInteger myValue = [[NSUserDefaults standardUserDefaults] integerForKey:storageKey];

Best way to store user information for my iOS app

What kind of database do you suggest? I want to store user email, username, password, and a couple other random pieces of information. It doesn't have to be fancy. Just a simple database. Are there any free options?
The user information needs to be stored in the keychain to keep it secure.
Any other information could be stored in any one of:
User defaults NSUserDefaults
File on disk (maybe a plist)
Database Core Data (technically just a file on disk)
Which you choose depends on what the data is, how much there is and what kind of access you need to it.
If your data is small and chosen by the user as some kind of setting then user defaults makes sense and is the lowest cost for you to implement.
To use a database, check out Core Data intro.
Wain is right but I think as you want to store small amount of data for further use, the most efficient ways is to use NSUserDefault.
NSUserDefault stores data in NSDictionary type things.
I think this is the step you have to take:
1- check if data exists. I mean if user selected the number if the last run of your app. So in viewDidLoad method:
NSMutableDictionary *userDefaultDataDictionary = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:ALL_DATA_KEY] mutableCopy];
if (userDefaultDataDictionary) {
// so the dictionary exists, which means user has entered the number in previous app run
// and you can read it from the NSDictionaty:
if(userDefaultDataDictionary[LABLE_KEY]){
//and store it
}
}
2 - you can implement some method like syncronize to store data in NSUserDefault every time something has been changed.
- (void) synchronize
{
NSMutableDictionary *dictionaryForUserDefault = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:ALL_DATA_KEY] mutableCopy];
if(!dictionaryForUserDefault)
dictionaryForUserDefault = [[NSMutableDictionary alloc] init];
dictionaryForUserDefault[LABLE_KEY] = //data you want to store
[[NSUserDefaults standardUserDefaults] setObject:dictionaryForUserDefault forKey:ALL_DATA_KEY];
[[NSUserDefaults standardUserDefaults] synchronize];
}
P.S. and don't forget to #define your keys for your dictionary:
#define LABLE_KEY #"Lables"
#define ALL_DATA_KEY #"AllData"
Store it in a plist. If you're talking about data pertaining to one or a few users, that's probably the easy thing. here is a simple example.
Since you say database, store in Sqlite. There's some provided stuff for it already in xcode.
The entire database is contained in one file, which can be moved around if you need to.
Here is some more information on how to use one in your app.

Resources