NSUserDefaults: Question about difference between two approaches - iphone

Problem
I want to store a NSString in NSUserDefaults and retrieve it later. I have a question about two different retrieving methods. Now at the top of the file I have:
// String used to identify the update object in the user defaults storage.
static NSString * const kLastStoreUpdateKey = #"LastStoreUpdate";
Method 1
NSString *lastUpdate = [[NSUserDefaults standardUserDefaults] objectForKey:kLastStoreUpdateKey];
Method 2
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *myString = [prefs stringForKey:kLastStoreUpdateKey];
Are there are significant differences I should know about? Also, can someone please explain what exactly is objectForKey? Apple's API states: that it "Returns the object associated with the first occurrence of the specified default." What exactly do they mean by the "specified default?
Thank you!

Generally you should use method 1.
that is "objectForKey".
Because, you know that, whatever you have stored in NSUserDefault. So, at the time of retriving it, you can catch the object with proper class like NSString, Array or any other user defined.
genrally "stringForKey" is not used.
If you are storing ingteger, BOOL into NSUserDefault then you should use intForKey, BOOLforKey, etc..
Cheers.

Related

How to store array of integer between app launches?

I want to store some data as a matrix of integers. For simplicity let's say I want to store this data in an array of integers. After each app launch I want to fill my model using this array. So the question is How to store arrays of integer in sandbox?
I don't want to write and rewrite data, maybe only once at first start.
What I tried:
I know about storing in plists and storing using NSCoding. But this strategies are used for more complicated models, not just arrays of integers.
EDIT:
is it faster to use c-arrays, storing them in txt-files and making own parser?
Plists and NSCoding are used for the simple integers as well.
However, you could just use the NSUserDefaults - that is the simples way:
[[NSUserDefaults standardUserDefaults] setObject:myArray forKey:#"AppData"];
Makes it easy to retrieve later from anywhere as well.
You can either store it in a plist, as you said, it's not a bad idea, it would work and do the job. It's not complicated at all, really, and not only used for complex models.
Else, you might want to use NSUserDefaults :
if (![NSUserDefaults standardUserDefaults] objectForKey:#"AKey"]) {
[[NSUserDefaults standardUserDefaults] setObject:yourArray forKey:#"AKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Don't forget that you need to wrap your integers into NSNumber.
A good practice for that would be using Objective-C's "new" notation : NSNumber * nb = #(42). That is much more readable that [NSNumber numberWithInt:42].
Good luck !
EDIT : According to your edit, no, don't use your own parser, at least for now. Don't try to optimize code when you don't really need it. Especially it it involves "breaking" Objective-C standards (and by that I mean using your own made stuff that might bug, and/or introduce strange behavior where Objective-C provides it's own way to do it). See this answer to know more about too much optimization.
+(void)storeArrayInDeviceWithKey:(NSArray *)arrData withKey:(NSString *)key{
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
[currentDefaults setObject:[NSKeyedArchiver archivedDataWithRootObject:arrData] forKey:key];
[currentDefaults synchronize];
}
For NSArray you need to little conversation with
NSKeyedArchiver archivedDataWithRootObject:UR OBJECT

How do you store multiple UIControlState instances in NSUserDefaults?

I'm looking to storing multiple instances of UIControlState within NSUserDefaults on the IOS platform.
Let's say there is a preference panel with various UIControl elements, be they UISlider, UISwitch etc.
Currently I have a loadPrefs function within viewWillAppear and a corresponding writePrefs within viewWillDisappear.
Rather than adding the code to store the state within NSUserDefaults for any future control that I add, is there an easy way to iterate through all the keys in NSUserDefaults and set the relevant states accordingly?
Is there a "proper" way of doing this via an NSArray or some other collection or is it not worth the time and bother?
You can get the entire NSUserDefaults stuff as an NSDictionary by using the dictionaryRepresentation method:
NSDictionary *dict = [[NSUserDefaults standardUserDefaults] dictionaryRepresentation];
for (NSString *key in [dict allKeys])
{
// do whatever you want
}
Hope this helps.

Access Variable From Any File

I have an objective-c/xcode project with several header and implementation files. I'd like to declare a variable that I can read and change from any file associated with the project. I tried doing extern int val = 0; in a header, but that lead to a linker error.
Would appreciate any help, thanks.
For storing and accessing an int in and iOS app, I recommend using NSUserDefaults.
You can set the value from anywhere in the application by
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setInteger:anInt forKey:#"IntKey"];
[defaults synchronize];
Then you can retrieve the value from anywhere in the application by
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
int a = [defaults integerForKey:#"IntKey"];
This also works great for BOOL, float, NSString and NSArray. Check out the NSUserDefaults documentation for more details and examples.
Put the:
extern int val;
in at least one header file included by any .m or .c file where you want to use this global variable. Including an assignment here is almost always an error.
Put
int val = 0;
outside any function or method scope, in exactly one .m or .c file included in your build. No more.
If you access this variable often, and care about performance and battery life, using NSDefaults is several orders of magnitude slower than accessing a global variable. Using the app delegate for singleton model objects is also somewhat slower, and produces slightly larger apps.

question on NSUserDefault Class

I have value in 1 string for particular key.
but NSUserDefault class method doesn't work properly and it doesn't set object of a string forkey .
in short setobject forkey method is not working of NSUserDefault class.
why is it so?
First of all, NSUserDefault class works just fine. It is called millions of times every day and works exactly as expected. The next likely culprit is your code. If you post that, it will be much easier to determine what you're doing wrong, and to make an appropriate suggestion.
(Edit added after OP's comment)
I just added this code:
//* TEST
NSString *string01 = #"Hardwork";
NSUserDefaults* defs111 = [NSUserDefaults standardUserDefaults];
[defs111 setObject:string01 forKey:#"first_name_textfield"];
NSString *test = [defs111 objectForKey:#"first_name_textfield"];
NSLog(#"Test: %#", test);
to my project and ran it and everything worked just fine.
As I stated above: NSUserDefault works like a champ. There's something you're not telling us about your use-case. Something important. ;)

Is there a better way to put a bunch of stuff in NSUserDefaults?

I'm confused about NSUserDefaults on the iPhone.
I come from a C / asm background and the Objective-C stuff has been a learning experience.
I'm currently using NSUserDefaults to store some strings (for the names in a highscore table). I want to start implementing a "Save Game" type feature so if the user gets a call or exits out of the game for a moment, they can come back to it.
To recover the game, I've got a couple of BOOL flags, a couple of ints to store some necessary variables, but I'm stuck at an array I need to store.
I have a 50 element array of unsigned chars. I could move it to ints if it would make things easier, but I'm just not seeing it.
To work with NSUserDefaults I can setBool (already doing that), setFloat (again, already doing that), setInteger, and setObject.
Obviously I could declare keys for each element of the array and store them one by one with setInteger but that's really kludgy. What's the best way to tackle this? Instead of an array of unsigned chars, I somehow try to use an NSObject? Are there any good tutorials on NSObjects that I can read through to understand it better?
Would Property Lists fit better with what you are trying to achieve?
You can create dictionary, store value for each setting or an array, and then dump it to Property List. You can easily read them back or update the values based on keys.
http://developer.apple.com/documentation/Cocoa/Conceptual/PropertyLists/...
You can pass an NSArray or an NSDictionary to NSUserDefaults with setObject:forKey:. It works just fine. Obviously, your array of unsigned chars would have to become an an NSArray of NSNumbers, which implies some overhead, but it's probably your easiest option.
Try using an NSData object, which can be directly stored to NSUserDefaults
[[NSUserDefaults standardUserDefaults] setObject:[NSData dataWithBytes:array length:len]
forKey:#"someArray"];
Whoa there, you should really look into using Core Data (or just sqllite) to store game state. NSUserDefaults is for what is says - defaults, configuration settings. It is not really meant to store largish chunks of binary data.
To convert a 50 element C array of unsigned chars in to an NSArray which you can store in a NSUserDefaults using:
NSMutableArray* a = [NSMutableArray new];
for ( int i = 0; i < 50; ++i ) {
[a addObject:[NSNumber numberWithInteger:yourArray[i]]];
}
[[NSUserDefaults standardUserDefaults] setObject:a forKey:#"theArray"];
[a release];
to get it back:
NSArray* a = [[NSUserDefaults standardUserDefaults] objectForKey:#"theArray"];
for ( int i = 0; i < 50; ++i ) {
yourArray[i] = [[a objectAtIndex:i] integerValue];
}
There is certainly no problem with using NSUserDefaults to store your game state, not when it is so small. If your game state was humoungous, you might want to investiage storing it as a plist file, but NSUserDefaults will not break a sweat handling this trivial amount of data.