How to save fields correctly with NSUserDefaults? - objective-c

I'm creating a program that saves a String from one text field and an integer from a second text field. I am trying to use NSUserDefaults, but I can't seem to get either of them to save correctly when I run the program. It crashes when I press the save button with the breakpoint while handling the NSUserDefaults. Am I doing something wrong? I skimmed through the documentation, but it didn't help. Can I even use 2 different instances of NSUserDefaults?
- (IBAction)save:(id)sender {
//Save stuff fropm textfields
NSString* name = _nameText.text;
int count = [_countText.text intValue];
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[[NSUserDefaults standardUserDefaults] setObject:name forKey:#"name"];
[[NSUserDefaults standardUserDefaults] setInteger:count forKey:#"count"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (IBAction)load:(id)sender {
//Load stuff from NSUserDefaults
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSString* loadstring = [defaults objectForKey:#"name"];
_nameText.text = loadstring;
NSUserDefaults* defaults2 = [NSUserDefaults standardUserDefaults];
NSInteger loadint = [defaults2 integerForKey:#"count"];
_countText.text = [NSString stringWithFormat:#"%li", (long)loadint];
}

Declare defaults = [NSUserDefaults standardDefaults]; in your viewDidLoad (and NSUserDefaults* defaults; in .h) and use this code:
- (IBAction)save:(id)sender {
//Save stuff fropm textfields
NSString* name = _nameText.text;
int count = [_countText.text intValue];
[defaults setObject:name forKey:#"name"];
[defaults setInteger:count forKey:#"count"];
[defaults synchronize];
}
- (IBAction)load:(id)sender {
//Load stuff from NSUserDefaults
_nameText.text = [defaults stringForKey:#"name"];
_countText.text = [NSString stringWithFormat:#"%li", (long)[defaults integerForKey:#"count"]];
}

Related

How to load the user’s last selected value for a slider when the app relaunches?

I am new to Xcode and I am using Objective C in OSX.
I am trying to load the user’s last selected value for a slider when the app relaunches.
my code for the slider is…
- (IBAction)sliderChanged:(id)sender {
amount = [self.amountSlider integerValue];
NSString *amountString = [NSString stringWithFormat:#"%ld", amount];
[self.amountLabel setStringValue:amountString];
}
I have this setter…
- (void)setInteger:(NSInteger)valueforKey:(NSString *)defaultName{
[[NSUserDefaults standardUserDefaults] setObject:#"amountString" forKey:#"amountSlider"];
}
I would like to know how to code the getter.
A step-by-step instructions with code will be appreciated.
Any improvements/corrections to my existing code above would also be appreciated.
Make separate functions for retrieving, saving from defaults like this.
- (void)saveValueToUserDefaults:(NSString *)pValue key:(NSString *)kKey {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[self removeValueFromUserDefaults:kKey];
[defaults setObject:pValue forKey:kKey];
[defaults synchronize];
}
- (void)removeValueFromUserDefaults:(NSString *)kKey {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:kKey]) {
[defaults removeObjectForKey:kKey];
}
}
- (NSString *)retriveValueFromUserDefaults:(NSString *)kKey {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:kKey]) {
return [defaults objectForKey:kKey];
} else {
return kStringEmpty;
}
}
This will make simple to save and retrieve values from defaults.
Like-
[self saveValueToUserDefaults:YOUR_AMOUNT forKey:YOUR_KEY];
and get like this,
YOUR_AMOUNT = [self retriveValueFromUserDefaults:YOUR_KEY];
You asked for it :D
in your class create integer variable called amountChecker = 0
create a function called checker like this :
-(void) checker {
if (amount == amountChecker){
[[NSUserDefaults standardUserDefaults] setObject:amountLabel.text forKey:#"amountSlider"];
}
else
amount = amountChecker;
}
then .. in this function :
- (IBAction)sliderChanged:(id)sender {
amount = [self.amountSlider integerValue];
NSString *amountString = [NSString stringWithFormat:#"%ld", amount];
[self.amountLabel setStringValue:amountString];
[self performSelector:#selector(checker) withObject:nil afterDelay:1];
}
now this code will only store your value if a second passes and your slider didn't change , instead of storing your value like 60 times every second :D
it all starts when you change the slider then after one second it will check if the value changed if not it will store it
and when you reopen the app you will use this code :
amount = [[NSUserDefaults standardUserDefaults] objectForKey:#"amountSlider"];

NSUserDefaults Arrays

I need two NSMutableArray that will contain NSString.
These arrays are:
ListOFUserNames=[NSMutableArray array];
SituationstoName =[NSMutableArray array];
I have two different sets of strings that go into each mutable array.
After named gets added to Listofusernames
Situation gets added to SituationstoName
[ListOFUserNames addObject:AfterNamed];
[SituationstoName addObject:Situation];
I am trying to save listofusernames and situationstoname with their respective strings.
NSUserDefaults *something = [NSUserDefaults standardUserDefaults];
[something setObject:ListOFUserNames forKey:#"somedata"];
[something synchronize];
NSUserDefaults *something2 = [NSUserDefaults standardUserDefaults];
[something2 setObject:SituationstoName forKey:#"somedata2"];
[something2 synchronize];
In the method that loads them, nothing comes out.
The code for that method is:
NSUserDefaults *somet = [NSUserDefaults standardUserDefaults];
NSUserDefaults *somet2 = [NSUserDefaults standardUserDefaults];
ListOFUserNames = [somet objectForKey:#"somedata"] ;
SituationstoName = [somet2 objectForKey:#"somedata2"] ;
[somet synchronize];
[somet2 synchronize];
The problem is that it is not loading the strings that are saved in the mutable arrays.
//initialise array
NSMutableArray *listOFUserNames=[[NSMutableArray alloc] init];
NSMutableArray *situationstoName =[[NSMutableArray alloc] init];
//add content in the array
[listOFUserNames addObject:AfterNamed];
[situationstoName addObject:Situation];
(Before storing also check if your array contains objects or is empty.)
//Store these array in `NSUserDefaults`
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:listOFUserNames forKey:#"NameData"];
[userDefaults setObject:situationstoName forKey:#"SituationData"];
[userDefaults synchronize];
//Access data where ever you want to be
//(listOFUserNames and situationstoName must be array)
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
listOFUserNames = [userDefaults objectForKey:#"NameData"] ;
situationstoName = [userDefaults objectForKey:#"SituationData"] ;

NSUserDefults returns null

I save a custom object in NSUserDefults the object has more than one property ,
i initialize the value of the custom object in the AppDelegate ,
my problem is that when i try to retrieve the custom object property "userToken" in the viewcontroller didLoad method it works and the data is correct but when i retrieve it in another method in the view controller i get NULL note that the other property "uId" returns the correct value and i'm retrieving the objects in same way
what did i do wrong here ? help is really appreciated
here's how i save and retrieve the object
+(void)SaveUser:(User *)user
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSData *userData = [NSKeyedArchiver archivedDataWithRootObject:user];
[userDefaults setObject:userData forKey:#"User"];
[userDefaults synchronize];
}
+(User*)retrieveUser
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
NSData *userData = [ud objectForKey:#"User"];
User *user = [NSKeyedUnarchiver unarchiveObjectWithData:userData];
return user;
}
and here's the implementation of the User object
- (id)initWithCoder:(NSCoder *)decoder
{
self = [super init];
if (self)
{
//uId and userToken are of type NSString
self.uId = [decoder decodeObjectForKey:#"UID"];
self.userToken = [decoder decodeObjectForKey:#"DeviceToken"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:self.uId forKey:#"UID"];
[encoder encodeObject:self.userToken forKey:#"DeviceToken"];
}
Try this :
Also note that + mean as static function that didn't have access to class properties make every thing in your saveuser or retrieveuser functions also decode without call another method out of class to decode it . that why maybe your + method get always null value when you use it out of loadview
+(void)SaveUser:(User *)user
{
NSUserDefaults *UserDefaults = [NSUserDefaults standardUserDefaults];
[UserDefaults setObject:[NSKeyedArchiver archivedDataWithRootObject:user] forKey:#"User"];
[UserDefaults synchronize];
}
+(User*)retrieveUser
{
NSUserDefaults *UserDefaults = [NSUserDefaults standardUserDefaults];
NSData *userData = [UserDefaults objectForKey:#"User"];
User *user = [NSKeyedUnarchiver unarchiveObjectWithData:userData];
return user;
}

NSUserDefaults not saving in table cell

When I replace the #"hello" with titlestring the table, the cell shows up blank, If i leave the hello, everything works, including the "detailsstring". I don't know why it's doing that since detailsstring is set up exactly the same as titlestring.
here is the code:
in the .m file I have
#synthesize detailsstring;
#synthesize titlestring;
and it's all defined the same in the .h in the .m I have this as well:
- (void)viewDidLoad{
titlestring =[[NSUserDefaults standardUserDefaults] objectForKey:#"titletext"];
detailsstring = [[NSUserDefaults standardUserDefaults] objectForKey:#"details"];
tabledata = [[NSArray alloc] initWithObjects:#"hello", nil];
tablesubtitles = [[NSArray alloc] initWithObjects:detailsstring, nil];
[super viewDidLoad];
}
Now, I'm saving those Userdefaults in another controller. Here is the save button action in a different view controller:
- (IBAction)saveButton:(id)sender {
NSUserDefaults *titletext = [NSUserDefaults standardUserDefaults];
[titletext setObject:titleTextfield.text forKey:#"titletext"];
NSUserDefaults *details = [NSUserDefaults standardUserDefaults];
[details setObject:detailstextfield.text forKey:#"details"];
NSUserDefaults *categoryUser = [NSUserDefaults standardUserDefaults];
[categoryUser setInteger:selectedCategory forKey:#"category"];
}
What am I doing wrong?
First of all, one instance of NSUserDefaults is sufficient for all three modifications. To 'push' the changes to the file system immediately, you can call [userDefaults synchronize];. Otherwise there is no guarantee that your changes are saved instantly. Apple suggests only to call this method if you cannot wait for the changes to be saved.
- (IBAction)saveButton:(id)sender {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:titleTextfield.text forKey:#"titletext"];
[userDefaults setObject:detailstextfield.text forKey:#"details"];
[userDefaults setInteger:selectedCategory forKey:#"category"];
[userDefaults synchronize];
}
In your viewDidLoad: method, try to output the saved values to test your application's integrity:
NSLog(#"%#", [[NSUserDefaults standardUserDefaults] objectForKey:#"details"]);

How to Read String from NSUserDefaults

I have an object at the root of plist that stores objects and keys (one of which is input from a user textfield). I have no problem writing and creating structure; it's trying to read values that causing problem. Below code I used to write the data, can someone tell me how to read the string [val] and [myKey]?
thank you!
#define defaultValue #"Your Name"
#define myKey #"PersonName"
- (void)textFieldAction:(id)sender {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *val;
// Get the new value from the textfield
val = [myTextField stringValue];
if ([val isEqualToString:defaultValue]) {
[defaults removeObjectForKey:myKey];
} else {
// [defaults setObject:val forKey:myKey];
NSDictionary *my_dict = [NSDictionary dictionaryWithObjectsAndKeys:
#"Name", #"PersonName",
#"Email", #"PersonEmail",
#"Dept", #"PersonDept",
#"Job", #"PersonJob",
val, myKey,
#"Status", #"PersonStatus",
nil];
[defaults setObject: my_dict forKey: #"Person"];
[[NSUserDefaults standardUserDefaults] registerDefaults:my_dict];
I would like to automatically populate the textfield with the [val], for [myKey], if the user has the info already in the plist. Here's the code I'm trying to use for that:
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
NSUserDefaults *defaults = [[NSUserDefaults standardUserDefaults] objectForKey:myKey];
NSString *val = [defaults stringForKey:myKey];
if (val == nil) val = defaultValue;
[myTextField setStringValue:val];
You can write the value into NSUserDefault like the following:
[[NSUserDefaults standardUserDefaults] setValue:[myTextField stringValue] forKey:#"Person"];
And read it later like the following:
[myTextField setStringValue:[[NSUserDefaults standardUserDefaults] stringForKey:#"Person"];
So you can simplify your code into:
- (void)textFieldAction:(id)sender {
[[NSUserDefaults standardUserDefaults] setValue:[myTextField stringValue] forKey:#"Person"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
You can set a default value with the registerDefaults:. And when you can retrieve that value simply by calling:
- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
// ...
[[NSUserDefaults standardUserDefaults] registerDefaults:#{#"Person", defaultValue}]
NSString *value = [[NSUserDefaults standardUserDefaults] stringForKey:#"Person"];
[myTextField setStringValue:value];
// ...
}
If I understand correctly, you should be able to do what you need by simply doing:
NSString * val = [[NSUserDefaults standardUserDefaults] objectForKey: myKey];
[textfield setText: val];
NSUserDefaults Reference Page
myTextField.text = [[NSUSerDefaults standardUserDefaults] objectForKey:myKey];