NSUserDefaults - storing basic settings - iphone

I have a flipView application. On the FlipView I keep settings for the MainView and would like to use NSUserDefaults to store 2 integers for the MainView. I will use those integers in the main application. Is there some basic code that can implement what I'm trying to do?
I'd like to store the information on the FlipView (if changed) and have a default setting when the program is first run in the MainView.
Also, will I need to release the NSUserDefaults object once I'm finished using it?

check out below code, I had wrapped and make easy for you,
you can use below codes by:
import "Settings.h" in any code where you want to use, (maybe AppDelegate.m) in your case. then
to set value, use
[Settings setSetting:#"AUTOLOGIN" value:#"1"];
[Settings setSetting:#"OTHERPROPERTY" value:#"100"];
and remember that, store pointer datatype only,
to get setting value:
[Settings getSetting:#"AUTOLOGIN"];
here below there are two files, Setting.h and Setting.m , make those
header file is :
#import <Foundation/Foundation.h>
#interface Settings : NSObject {
}
+(id) getSetting:(NSString *)key;
+(void) setSetting:(NSString *)key value:(id)v;
#end
- and implementation file is
#import "Settings.h"
#implementation GCCSettings
static NSMutableDictionary *settings = nil;
+(id) getSetting:(NSString *)key{
if(settings == nil){
settings = [[NSMutableDictionary alloc] initWithDictionary:
[[NSUserDefaults standardUserDefaults] dictionaryForKey:#"settings"]
];
}
return [settings objectForKey:key];
}
+(void) setSetting:(NSString *)key value:(id)v{
[settings setValue:v forKey:key];
[[NSUserDefaults standardUserDefaults] setObject:settings forKey:#"settings"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
#end
and finally don't release any objects, which you had not allocated using(new, init, retain etc).

You can store the integer with
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:#"theKey"] and retrive it with [[NSUserDefaults standardUserDefautls] integerForKey:#"theKey"]. That's really all you need to handle an integer with user defaults.
You don't release the NSUserDefaults object. It's a singleton, so only one will be created for the life of your app. You also don't own it which means you wouldn't be releasing it.

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;

saving in NSUserDefaults

I'm having a problem on how/where I can save my NSUserDefaults for applicationDidEnterBackground and applicationWillTerminate, I need to save my NSArray count in NSUserDefaults from another UIViewController when user exits the app or enter background. But I don't know if I would save the right integer, because my NSArray count is being updated when I am deleting on it on UIView.
I cant save it on viewDidLoad and viewDidAppear. Hope someone would help. Thankyou.
If u need to save from another ViewController then its better u add NSMutableArray in appDelegate. Whenever you delete or add object then save the count of array as it will overwrite like this:
[[NSUserDefaults standardUserDefaults] setInteger:[yourArray count] forKey:#"Count"];
[[NSUserDefaults standardUserDefaults] synchronize];
Retrieve like this:
NSInteger count = [[NSUserDefaults standardUserDefaults] integerForKey:#"Count"];
EDIT : synchronize : Writes any modifications to the persistent domains to disk and updates all unmodified persistent domains to what is on disk.
Refer NSUserDefaults_Class as clearly states gets called perodically and we don't have to wait for their call
Create the required NSMutableArray in your appDelegate class i.e create a property of NSMutableArray iVar,then later you can update ,add ,delete contents from it in any of the classes.Thus you shall get the array count in the applicationDidEnterBackground and applicationWillTerminate notification functions in the appDelegate function itself and the array count should be accurate..
in yourAppDelegate.h
create ..
#interface yourAppDelegate : UIResponder <UIApplicationDelegate>{
NSMutableArray *myArray;
}
#property(nonatomic,strong)NSMutableArray *myArray; //replace strong by retain if ios <5
in yourAppDelegate.m
#synthesize myArray;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *
)launchOptions{
self.myArray = [NSMutableArray array];
}
further in your required functions in appDelegate.m file
- (void)applicationWillTerminate:(UIApplication *)application
{
[[NSUserDefaults standardDefaults]setValue:[NSNumber numberWithInt:[self.myArray count] forKey:#"myOwnKey"]];
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
in case if you want to add objects to this array in any other class just create a delegate of the yourAppDelegate .
Eg in viewDidLoad of class A,
-(void)viewDidLoad{ // assuming viewController A
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplicatio sharedApplication]delegate];
[appDelegate.myArray addObject:#"1232"];
}
You can use this code to save value to NSUserDefaults
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:yourArray forKey:#"YourKey"]
[defaults synchronize];
For details on using NSUserDefault check this
[[NSUserDefaults standardUserDefaults] setBool:<#(BOOL)#> forKey:<#(NSString *)#>], this Is for Boolean you an add setInt/setFloat/SetDouble etc and even ObjectiveC objects with setValue/setObject.
[[NSUserDefaults standardUserDefaults] setValue:<#(id)#> forKey:<#(NSString *)#>];
[[NSUserDefaults standardUserDefaults] setObject:<#(id)#> forKey:<#(NSString *)#>];
To retrieve the value you can use getters like boolForKey ([[NSUserDefaults standardUserDefaults] boolForKey:<#(NSString *)#>]) intForKey etc..
Use removeObjectForKey to remove objects.

How to access the string data outside the function and class

I am trying to access the nsstring data out side the function and also outside the class.
How can I access useridStr outside the function and class? This is my code:
-(id)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *loginStatus = [[NSString alloc] initWithBytes:[webData mutableBytes]
length:[webData length] encoding:NSUTF8StringEncoding];
NSDictionary *loginDict = [[loginStatus JSONValue] objectForKey:#"UserDetails"];
NSArray *userId = [loginDict valueForKey: #"userid"];
NSString *useridStr = [userId lastObject];
NSLog(#"--------------....%#", useridStr);
}
NSUserDefaults *pre = [NSUserDefaults standardUserDefaults];
[pre setObject:useridStr forKey:#"useridStr"];
where you want to need string:
NSUserDefaults *pre =[NSUserDefaults standardUserDefaults];
NSString * useridStr =[pre stringForKey:#"useridStr"];
OR
In .h file of anotherView
-(id)initUserInfo:(NSString *)string;
In .m file of anotherView
-(id)initUserInfo:(NSString *)string{
if (self = [super initWithNibName:#"nextView" bundle:nil]) {
useridStr=string
}
return self;
}
In .m File of firstView
-(IBAction)btnNext_TouchUpInside:(id)sender{
nextView *second =[[nextView alloc]initUserInfo:useridStr];
[self presentModalViewController:second animated:NO];
}
What Piyush suggested is also correct. But there is also another way to achieve it.
As he suggested NSUserDefaults to save data you should keep in mind that NSUserDefaults is generally used to save data like preferences which you want it to be stored even after Application is closed by user and you want those data again when you start your application.
So if you want to save data like preferences go for NSUserDefaults. If you want your data to be available throughout your application while its running and you do not need to save them like preferences I would recommend you declare that object globally in Appdelegate file and access them whenever you need. You should not store them as NSUserDefaults because as Apple document says whatever you store in NSUserDefaults it will be saved in user's default database. So that will consume memory of your device. So in short saving everything to NSUserDefaults won't be a good idea if we consider memory managent concepts.

NSUserDefaults not present on first run on simulator

I've got some settings saved in my Settings.bundle, and I try to use them in application:didFinishLaunchingWithOptions, but on a first run on the simulator accessing objects by key always returns nil (or 0 in the case of ints). Once I go to the settings screen and then exit, they work fine for every run thereafter.
What's going on? Isn't the point of using default values in the Settings.bundle to be able to use them without requiring the user to enter them first?
If I got your question right, in your app delegate's - (void)applicationDidFinishLaunching:(UIApplication *)application, set the default values for your settings by calling
registerDefaults:dictionaryWithYourDefaultValues
on [NSUserDefaults standardUserDefaults]
- (void)applicationDidFinishLaunching:(UIApplication *)application {
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:3], #"SomeSettingKey",
#"Some string value", #"SomeOtherSettingKey",
nil];
[ud registerDefaults:dict];
}
These values will only by used if those settings haven't been set or changed by previous executions of your application.
As coneybeare said "You should detect if it is the first load, then store all your defaults initially."
On applicationDidFinishLaunching try to set default value in your preference.
Here is the sample:
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
if([defaults objectForKey:#"YOUR_KEY"] == nil)
{
[defaults setValue:#"KEY_VALUE" forKey:#"YOUR_KEY"];
}
When application will run second time it will come with KEY_VALUE for YOUR_KEY.
Thanks,
Jim.
Isn't the point of using default
values in the Settings.bundle to be
able to use them without requiring the
user to enter them first?
No. The point of the settings bundle is to give the user a place to edit all 3rd Party app settings in a convenient place. Whether or not this centralization is really a good idea is a User Experience issue that is off topic.
To answer your question, you should detect if it is the first load, then store all your defaults initially.
And while we are on the subject, I would also check out In App Settings Kit as it provides your app with a simple way to display your app settings in both places (in-app and Settings.app) with minimal code.
The values in the Settings.bundle are intended for the Settings app to able to fill in default values for your app. They are not used by your own app.
But you can set defaults yourself with the registerDefaults: method of NSUserDefaults. This will not actually set them on disk but just give "defaults for the defaults": they are used when no value has been set by the user yet.
Setting registerDefaults: must be done before any use of the default values. The "applicationDidFinishLaunching:" method that others suggested for this, is too late in most cases. By the time "applicationDidFinishLaunching:" is called, your views have already been loaded from the nib files, and their "viewDidLoad:" methods have been called. And they may typically read user defaults.
To guarantee that the defaults are set before first use, I use the following utility class, which loads the values from the Root.plist file and sets them with "registerDefaults:". You use this class to read user defaults instead of "[NSUserDefaults standardUserDefaults]". Use "[Settings get]" instead.
As a bonus, it also contains a registration method for user default change notifications, because I always forget how that is done.
#import "Settings.h"
#implementation Settings
static bool initialized = NO;
+ (void) setDefaults
{
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *settingsBundlePath = [bundlePath stringByAppendingPathComponent:#"Settings.bundle"];
NSBundle *settingsBundle = [NSBundle bundleWithPath:settingsBundlePath];
NSString *settingsPath = [settingsBundle pathForResource:#"Root" ofType:#"plist"];
NSDictionary *settingsDict = [NSDictionary dictionaryWithContentsOfFile:settingsPath];
NSArray *prefSpecifierArray = [settingsDict objectForKey:#"PreferenceSpecifiers"];
NSMutableDictionary *appDefaults = [[NSMutableDictionary alloc] init];
for (NSDictionary *prefItem in prefSpecifierArray)
{
NSString *key = [prefItem objectForKey:#"Key"];
if (key != nil) {
id defaultValue = [prefItem objectForKey:#"DefaultValue"];
[appDefaults setObject:defaultValue forKey:key];
}
}
// set them in the standard user defaults
[[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
if (![[NSUserDefaults standardUserDefaults] synchronize]) {
NSLog(#"Settings setDefaults: Unsuccessful in writing the default settings");
}
}
+ (NSUserDefaults *)get
{
if (!initialized) {
[Settings setDefaults];
initialized = YES;
}
return [NSUserDefaults standardUserDefaults];
}
+ (void) registerForChange:(id)observer selector:(SEL)method
{
[[NSNotificationCenter defaultCenter] addObserver:observer selector:method name:NSUserDefaultsDidChangeNotification object:nil];
}
+ (void) unregisterForChange:(id)observer
{
[[NSNotificationCenter defaultCenter] removeObserver:observer name:NSUserDefaultsDidChangeNotification object:nil];
}

how can i store value in an NSArray using WritetoFile?

i wana store the index of seleted cell of table using NSArray, can u help me....
You can use user defaults or property list for this.
Example on user defaults. You have a controller class that has access to the index and will load it at startup and write it into plist whenever it's updated:
If you have some kind of controller class then you would put this code into + (void)initialize, it initialises the variable if it does not exists in plist:
+ (void)initialize
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults =
[NSDictionary dictionaryWithObject:[NSNumber numberWithInteger:5]
forKey:#"MyFunnyIndex"];
[defaults registerDefaults:appDefaults];
}
In your -(void)awakeFromNib (I'm assuming you're using some kind of controller class) load your last stored value:
-(void)awakeFromNib
{
int index =
[[NSUserDefaults standardUserDefaults] integerForKey:#"MyFunnyIndex"];
[somethingThatNeedsIndex setIndex:index];
// ...
}
Somewhere where the index is updated (or where you want to write it to plist), let's call it - (void)updateInterface:
- (void)updateInterface
{
[[NSUserDefaults standardUserDefaults]
setObject:[NSNumber numberWithInteger:index]
forKey:#"MyFunnyIndex"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
I don't know if I understand the question correctly, but it sounds like you could use a property list to store this information. Property lists are very easy to use and quite efficient with small amounts of data.
Read the "Property List Programming Guide" for further explanation. There is even a tutorial in there.