problem with loading from NSUserDefaults, obj-c - objective-c

I'm having a problem with NSUserDefaults. I'm saving a name, then trying to access it later in the code from another view controller, but it seems that my key is empty or not saved as when I display the string from the key my label is blank.
-(void) saveName {
NSString *name = nameField.text;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:name forKey:#"playersName"];
[defaults synchronize];
}
-(void) viewDidLoad // method called later on in code from different viewcontroller
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *name = [defaults objectForKey:#"playersName"];
playerName.text = name; // player name == myLabel
if ([[NSUsersDefaults standardUserDefaults] objectForKey:#"playersName"] == nil) {
playerName.text =#" blank";
}
}
My string doesn't seem to be saving to userdefaults as the #"blank" string keeps showing up with my label. I'm not too familiar with NSUserDefaults so any help is much appreciated.

A few things to note when using NSUserDefaults:
calls to syncrhonize method is not necesary and will only make it slower if your program is multi threaded.
Check if the key that you use is being used by other libraries in your project
Check if the value that you set to the key is not nil
Try to use stringForKey: or boolForKey: instead of objectForKey:
I had troubles a few times with NSUserDefaults but in the end it's usually my code that's problematic.

I would suggest you to check whether your '(void) saveName' method is being called or not... Put some breakpoint and see the result

Related

How exactly to save and retrieve last seen message timestamp - plist or NSUserDefaults

I have two UIViewControllers. In the FirstViewController, I download the groupsInfo data from the firebase and show the details(groupName,lastMessage) in the UITableView and have one more label "lastMessageTime"(this information will come from SecondViewController).Once I tap the UITableView cell, it goes to the detail page SecondViewController, here I download the messageInfo based on the tapped groupID. When I leave the SecondViewController, I want to store the last message time for that particular groupID in commonplace (either plist or NSUserDefaults) and retrieve the information in the FirstViewController or in some other ViewController(later stage). The saved data shouldn't get deleted and also I should be able to update(in case value already exist for particulat key) "lastMessageTime" for any particular groupID whenever there is new message.
Below is code I tried, but not sure if this is the best approach. Would be great if you can tell me the best approach to deal this requirement effectively.
SecondViewController:
-(void)viewWillDisappear:(BOOL)animated{
[self updateLastMessageSeenTime:groupID];
}
-(void)updateLastMessageSeenTime:(NSString*)groupID
{
FIRDataSnapshot *snapshot = [self.messageArray lastObject];
NSMutableDictionary *lastSeenMessageTime = [[NSMutableDictionary alloc]init];
NSString *lastMessageTime = snapshot.value[#"timeStamp"];
[lastSeenMessageTime setValue:lastMessageTime forKey:groupID];
NSUserDefaults *lastSeenMessageTimeUserDefaults = [NSUserDefaults standardUserDefaults];
[lastSeenMessageTimeUserDefaults setObject:lastSeenMessageTime forKey:#"lastMessageTimeArrayKey"];
[lastSeenMessageTimeUserDefaults synchronize];
}
Above method erases all the previous data. For Example, If visited the SecondViewController twice each for different groupID, previous groupID's lastMessageTime is removed and replaced with the new groupID's.
You need to get the dictionary from NSUserDefaults first and if it doesn't exist then init a new one. Try this.
-(void)updateLastMessageSeenTime:(NSString*)groupID
{
FIRDataSnapshot *snapshot = [self.messageArray lastObject];
NSUserDefaults *lastSeenMessageTimeUserDefaults = [NSUserDefaults standardUserDefaults];
NSString *key = #"lastMessageTimeArrayKey";
NSMutableDictionary *lastSeenMessageTime = [[lastSeenMessageTimeUserDefaults objectForKey: key] mutableCopy];
if (!lastSeenMessageTime) {
lastSeenMessageTime = [[NSMutableDictionary alloc] init];
}
NSString *lastMessageTime = snapshot.value[#"timeStamp"];
[lastSeenMessageTime setValue:lastMessageTime forKey:groupID];
NSUserDefaults *lastSeenMessageTimeUserDefaults = [NSUserDefaults standardUserDefaults];
[lastSeenMessageTimeUserDefaults setObject:lastSeenMessageTime forKey: key];
[lastSeenMessageTimeUserDefaults synchronize];
}

Saving NSUserDefaults Issue?

i have been working on a app, and needed to store a string. I used this code to set the default:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:CertificateKey.stringValue forKey:#"SavedKey"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"%#",[defaults objectForKey:#"SavedKey"]);
I loged it, so i know it saved...well, it showed me the value.
When i open my application, I use this to retrieve the default:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[CertificateKey setStringValue:[defaults objectForKey:#"SavedKey"]];
[CertificateKey setTitleWithMnemonic:[defaults objectForKey:#"SavedKey"]];
[[NSUserDefaults standardUserDefaults] synchronize];
Why will it not get the default value? Did i not completely save it?
Don't quit the application by pressing the stop button in xcode. Instead, quit it by right clicking on the application icon and selecting "Quit".
Edit
Maybe the first time that you execute the application, you want to save some defaults but you don't want to set them the second+ time that the application runs.
For this purpose in some class initialize method register the defaults, like this:
+ (void) initialize
{
NSUserDefaults* defaults= [NSUserDefaults standardUserDefaults];
[defaults registerDefaults: #{} ];
// This case it's an empty dictionary, but you can put whatever you want inside it.
// just convert it to data if it's not an object storable to a plist file.
}
Also, you're using setValue:forKey: , that method is inherited from NSObject. Use setObject:forKey: .
And use finalize if you want to save the defaults at the end:
- (void) finalize
{
// Save the defaults here
}
You might have a problem because you are creating an instance of NSUserDefaults. From what I understand you are supposed to access it like so: [[NSUserDefaults standardUserDefaults] setValue:#"Pikachu" forKey:#"Best Pokemon Ever"]; [[NSUserDefaults standardDefaults] objectForKey:#"Best Pokemon Ever"]; Rather than actually creating an instance of it.

Reload contents at startup

I've been banging my head against the wall for several days trying to understand how to perform an action as soon as the application starts.
Basically I want to download a plist from my website if the user turns on a switch that determines if he wants to download new contents at startup.
Point is that:
"A" class has the method to reload the contents;
"B" class has the switch that, if turned on, tells the delegate to perform the reload contents method as soon as the application starts
Now, I don't know how to tell the AppDelegate to run the method of class "A" if the switch of class "B" is turned on. Obviously I need to use NSUserDefaults, but i'm pretty lost after that.
Can anyone make things clearer? Or, is there a more comfortable workaround to do it?
yes you can do this using NSUserDefaults
in your class b.
-(void)swithChanged
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//check if !null
if(![[defaults objectForKey:#"shouldDownload"]isKindOfClass:[NSNull class]]){
if([(NSNumber*)[defaults objectForKey:#"shouldDownload"]boolValue])
{
[defaults setObject:[NSNumber numberWithInt:0] forKey:#"shouldDownload"];
[defaults synchronize];
}else{
[defaults setObject:[NSNumber numberWithInt:1] forKey:#"shouldDownload"];
[defaults synchronize];
}
}else{
//set your NSUserDefault here for the first time
}
}
in your AppDelegate
- (void)applicationDidBecomeActive:(UIApplication *)application{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//check if !null
if(![[defaults objectForKey:#"shouldDownload"]isKindOfClass:[NSNull class]]){
if([(NSNumber*)[defaults objectForKey:#"shouldDownload"]boolValue])
{
//you can write the downloadData method in this appDelegate,
//[self downloadData]
//OR
AClass *aClass = [AClass alloc]init];
[aClass downloadData];
}else{
//do not download
}
}else{
//the default behaviour of app, download or not?
}
}
Here's a post that could help you understand the flows during application start-up:
http://www.cocoanetics.com/2010/07/understanding-ios-4-backgrounding-and-delegate-messaging
Also, check this post:
applicationWillEnterForeground vs. applicationDidBecomeActive, applicationWillResignActive vs. applicationDidEnterBackground

Trying to save and set UISwitch state with NSUserDefaults

This is supposed to save the value of two UISwitches to NSUserDefaults and then set the switches on load based on the values saved to the defaults. I've been at this for hours but I can't seem to get it to work. Any help would be greatly appreciated.
The toggles are in a View that I'm using for settings. There are only two toggles, so I want to use NSUserDefaults. Toggles default to OFF. I want to toggle to ON and have that change be saved so that I can change the User experience based on the toggle's value. Then, when the User opens the settings again, I want them to display their current saved state.
I think that the value is being saved, but it is not being applied to the Switches when I reenter the Settings View.
- (IBAction)setBeadVibratorBySwitchState:(id)sender
{
if (setBeadVibrator.selected == YES) {
NSUserDefaults *beadSettings = [NSUserDefaults standardUserDefaults];
[beadSettings setBool:NO forKey:#"beadSwitchStatus"];
[beadSettings synchronize];
}
if (setBeadVibrator.selected == NO) {
NSUserDefaults *beadSettings = [NSUserDefaults standardUserDefaults];
[beadSettings setBool:YES forKey:#"beadSwitchStatus"];
[beadSettings synchronize];
}
NSLog(#"Bead Executed");
}
- (IBAction)setDecadeVibratorBySwitchState:(id)sender
{
if (setDecadeVibrator.selected == YES) {
NSUserDefaults *decadeSettings = [NSUserDefaults standardUserDefaults];
[decadeSettings setBool:NO forKey:#"decadeSwitchStatus"];
[decadeSettings synchronize];
}
if (setDecadeVibrator.selected == NO){
NSUserDefaults *decadeSettings = [NSUserDefaults standardUserDefaults];
[decadeSettings setBool:YES forKey:#"decadeSwitchStatus"];
[decadeSettings synchronize];
}
NSLog(#"Decade Executed");
}
- (void)viewDidLoad
{
[super viewDidLoad];
setBeadVibrator.selected = [[NSUserDefaults standardUserDefaults] boolForKey:#"beadSwitchStatus"];
setDecadeVibrator.selected = [[NSUserDefaults standardUserDefaults] boolForKey:#"decadeSwitchStatus"];
}
NSUserDefaults can only store objects of type NSData, NSString, NSNumber, NSDate, NSArray, or NSDictionary. So, I suggest that you put the state of the switch in an NSString and put that string in the NSUserDefaults. Than when you retrieve the info from the NSUserDefaults, you can use an if statement to set the value of the boolean again.
If you are using UISwitch, you should set the on property, instead of selected.
setBeadVibrator.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"beadSwitchStatus"];
setDecadeVibrator.on = [[NSUserDefaults standardUserDefaults] boolForKey:#"decadeSwitchStatus"];
see UISwitch Class Reference
I would suggest that you put the NSLog statements in the if-statements to see if they are really saved. If not, your UISwitches may not be configured properly with the UIControlEventValueChanged event.
You can read up more from Apple doc. Here is a very detailed website on using UISwitches.

Problems in loading from NSUserDefaults

I have a very strange problem while my app loads from NSUserDefaults.
This is the code in my appDelegate:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *user = [[NSString alloc]initWithString:[defaults objectForKey:#"_settingsUsername"]];
NSString *password = [[NSString alloc]initWithString:[defaults objectForKey:#"_settingsPassword"]];
NSString *instance = [[NSString alloc]initWithString:[defaults objectForKey:#"_settingsInstance"]];
The error is this: [NSPlaceholderString initWithString:]: nil argument'
It's very strange because i put in Settings.bundle -> Root.plist the default values for all the fields above.
Oddly that's how it's supposed to work -- this confused me too initially.
I guess the thing to remember is that you can use NSUserDefaults without the Settings.bundle, so it can't be the only way to set default values.
Apple provide sample code, AppPrefs, that shows how to copy the default value from the settings to NSUserDefaults.
Why don't you just use that?
NSUserDefaults *defaults = [NSUserDefaults standarduserDefaults];
NSString *user = [defaults objectForKey:#"_settingsUsername"];
NSString *password = [defaults objectForKey:#"_settingsPassword"];
NSString *instance = [defaults objectForKey:#"_settingsInstance"];
And make sure that there are objects for these keys.
hope it helps
I think the problem is that if the user hasn't gone into the settings for your app yet then all values returned from NSUserDefaults for those keys are nil. You need to handle that case and act accordingly - probably by going into the Settings.bundle and picking out the default value that you have put in there. I would just write a method that gets the value for a key and if NSUserDefaults returns nil it handles all the querying of the settings bundle for you.