how to check nsuserdefaults is empty or not - iphone

i am getting a list of items from sqlite database and place them in an array.
i need to get this array first time my app runs.
for this i am saving this array into NSuserdafaults.
my code is like this
if ([[NSUserDefaults standardUserDefaults] arrayForKey:#"categories"]) {
[[NSUserDefaults standardUserDefaults] setObject:appdelegate.categoriesList forKey:#"categories"];
NSLog(#"categorylist>>>>>> %#",appdelegate.categoriesList);
}
categoriesArray = [[NSMutableArray alloc]init];
categoriesArray = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"categories"] mutableCopy];
then it not entered into if condition.
and if i try with not equal like this.
if (![[NSUserDefaults standardUserDefaults] arrayForKey:#"categories"]) {
[[NSUserDefaults standardUserDefaults] setObject:appdelegate.categoriesList forKey:#"categories"];
NSLog(#"categorylist>>>>>> %#",appdelegate.categoriesList);
}
categoriesArray = [[NSMutableArray alloc]init];
categoriesArray = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"categories"] mutableCopy];
then enter for every build and run.
But i need this for first build and run i mean at installing time.
can any one please help me.
Thank u in advance.
(let me add comment if any one did n't understand my question)

categoriesArray = [[NSMutableArray alloc]init];
categoriesArray = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"categories"] mutableCopy];
The lines above create a leak: you first allocate one array, and then you immediately assign a different array to the same pointer that was keeping track of the array that you allocated. After the second line, you have no way to release the first array.
As for the main question, I suspect that the check
if (![[NSUserDefaults standardUserDefaults] arrayForKey:#"categories"]) {
succeeds every time because there's never a value written for the key #"categories". I see that the lines inside that conditional block try to write a value, but appdelegate.categoriesList may well be nil.

Related

Why can I return a NSMutableArray from NSUserDefaults but not an NSMutableDictionary

I'm saving several items in NSUserDefaults in iOS 6. In the past I have always used an NSMutableArray that contains NSMutableDictionaries to save some info. But now I've decided it would be more efficient to use an NSMutableDictionary that contains NSMutableDictionaries. I want to be able to delete dictionaries from the main NSMutableDictionary and modify the values stored in the subdictionaries.
I've been storing my main NSMutableArray as:
-(NSMutableArray *)listArray
{
return [[NSUserDefaults standardUserDefaults] mutableArrayValueForKey:#"list_array"];
}
-(void) setDeviceListArray:(NSMutableArray *)listArray
{
[[NSUserDefaults standardUserDefaults] setObject:listArray forKey:#"list_array"];
}
I would do the same for NSMutableDictionary but there is no getter function like 'mutableDictionaryValueForKey' that exists. Can someone tell me why this is??
just because :D
copy the dictionary like this
NSMutableDictionary *d = [[NSUserDefaults standardUserDefaults] dictionaryForKey:#"bla"].mutableCopy;

Settings Bundle values not being linked correctly on iPhone

I have an issue I've been struggling with for the last few days. I have a settings bundle, root.plist, which holds some user preferences. In it are three multivalue menu items. One returns a boolean, the other two return numbers.
When I call [[NSUserDefaults standardUserDefaults] dictionaryRepresentation] and examine it in the console, only the first item in the property list shows up with its value. The other two are conspicuously absent. As a result, when I try to retrieve those values, I get zero.
What's weirder is that the settings bundle looks correct in the Settings app on the iPhone. The only thing not working is that the values are not getting passed. As far as my app is concerned, the other two multivalue menu items don't even exist.
Any suggestions are greatly appreciated.
I've used this block of code, multiple times, in applicationDidFinishLaunchingWithOptions to initialize my user defaults.
if (![[NSUserDefaults standardUserDefaults] objectForKey:#"somePropertyYouExpect"]) {
NSString *mainBundlePath = [[NSBundle mainBundle] bundlePath];
NSString *settingsPropertyListPath = [mainBundlePath
stringByAppendingPathComponent:#"Settings.bundle/Root.plist"];
NSDictionary *settingsPropertyList = [NSDictionary
dictionaryWithContentsOfFile:settingsPropertyListPath];
NSMutableArray *preferenceArray = [settingsPropertyList objectForKey:#"PreferenceSpecifiers"];
NSMutableDictionary *registerableDictionary = [NSMutableDictionary dictionary];
for (int i = 0; i < [preferenceArray count]; i++) {
NSString *key = [[preferenceArray objectAtIndex:i] objectForKey:#"Key"];
if (key) {
id value = [[preferenceArray objectAtIndex:i] objectForKey:#"DefaultValue"];
[registerableDictionary setObject:value forKey:key];
}
}
[[NSUserDefaults standardUserDefaults] registerDefaults:registerableDictionary];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Make sure you are using - (void)registerDefaults:(NSDictionary *)dictionary on NSUserDefaults. Otherwise your defaults will not get pulled from the Bundle.
You have to do this early in your application, before you try to retrieve any of the default values.
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSUserDefaults_Class/Reference/Reference.html

Crash while fetching NSUserDefaults

The following code is crashing for me
[[NSUserDefaults standardUserDefaults] dictionaryForKey:#"2453"];
I checked and found that there is no key with name 2453 in NSUserDefaults. I am running the application for first time so this key will not be there but will be added later point in time. How to ignore this crash.
If this line
[[NSUserDefaults standardUserDefaults] dictionaryForKey:#"2453"];
is the line that is crashing, you might try this instead
NSDictionary *dict = nil;
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"2453"] != nil)
dict = [[NSUserDefaults standardUserDefaults] dictionaryForKey:#"2453"];
if (dict) {
...
}
My hunch is that in this case dictionaryForKey is calling objectForKey behind the scenes and blindly trying to cast nil to NSDictionary for you, which would, I think, cause a crash. But by checking yourself first if there is any kind of object for that key, you can avoid the crash. Give it whirl and report back! :-)
[[NSUserDefaults standardUserDefaults] dictionaryForKey:#"2453"];
// ^^ ^
The "key" in -dictionaryForKey: must be an NSString. It cannot be an int. So although the key you supplied consists only of numbers, you still have to pass in a string using #"...". The fact that the key is absent is irrelevant to the crash.
if ([[NSUserDefaults standardUserDefaults] dictionaryForKey:#"2453"]) {
// this line will only be reached if there is something for #"2453"
}

retain array into NSDefault?

HI all,
can we retain an array in NSDefualt?
regards
shishir
If you mean store an array, then the answer is yes. You just use the setObject:forKey: method to store it. So:
NSArray* myArray = [NSArray arrayWithObjects:#"One", #"Two", #"Three", nil];
[[NSUserDefaults standardUserDefaults] setObject:myArray forKey:#"myArrayKey"];
// much later...
NSArray* thatArray = [[NSUserDefaults standardUserDefaults] arrayForKey:#"myArrayKey];
NSLog(#"thatArray second object: %#", [thatArray objectAtIndex:1]);
// prints "thatArray second object: two"
I guess that you are asking for:
You have an array, you put it into NSUserDefaults, then later, you want to retain that array, is it right?
NSUserDefaults will not retain your array when you put it into. It just save and get data through serialization to a database
So, if you currently hold your array, you don't need to retain it any more.

Cannot read values from [NSUserDefaults standardUserDefaults] after synchronize

In the Application Delegate didFinishLaunching method, I am using the following code to build up a new NSDictionary to be used as the new settings bundle for the user:
NSNumber *testValue = (NSNumber*)[[NSUserDefaults standardUserDefaults] objectForKey:#"settingsversion"];
if (testValue == nil)
{
NSNumber *numNewDB = [NSNumber numberWithBool:NO];
NSNumber *numFirstUse = [NSNumber numberWithBool:YES];
NSDate *dateLastStatic = [NSDate date];
NSDate *dateLastMobile = [NSDate date];
NSNumber *numSettingsversion = [NSNumber numberWithFloat:1.0];
NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
numNewDB, #"newdb",
numFirstUse, #"firstuse",
numSettingsversion, #"settingsversion",
dateLastStatic, #"laststaticupdate",
dateLastMobile, #"lastmobileupdate",
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Later in another ViewController I am trying to read back a value from that same Dictionary, saved as the NSUserDefaults - well at least I thought it would, but I don't get any valid object pointer for the desired member lastUpdate back there:
in .h file:
NSDate *lastUpdate;
in the .m file in a member function:
lastUpdate = (NSDate *)[[NSUserDefaults standardUserDefaults] objectForKey:#"laststaticupdate"];
Even, if I print out the content of [NSUserDefaults standardUserDefaults] I only get this:
2010-04-29 15:13:22.322 myApp[4136:207] Content of UserDefaults: <NSUserDefaults: 0x11d340>
This leads me to the conclusion that there is no standardUserDefaults dictionary somewhere in memory or it cannot be determined as such a structure.
Edit: Every time, I restart the app ión the device, the check for testValue is Nil and I am building up the dictionary again but after one run it should be persistent on the Phone, right?
Am I doing something wrong somewhere in between? I have the feeling that I yet didn't really understand how to load and save settings persistent for a certain application on the iPhone.
Is there anything I have to do additionally to this? Integrating a settings.bundle in XCode or saving the dictionary manually to the Documents folder?
Can someone help me out here? Thanks a lot!
registerDefaults doesn't actually write anything to disk. It just creates a 'defaults defaults' dictionary in memory. So everytime you restart the app, testValue should be nil.
If you want to set persistent values, use setObject:forKey:.
I don't know why you aren't getting a valid object back however.