NSUserDefults returns null - objective-c

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;
}

Related

How to save a custom object to NSUserDefault which contains UIImage and NSMutableArray? [duplicate]

This question already has answers here:
Save images in NSUserDefaults?
(13 answers)
Closed 6 years ago.
In my project I need to save a custom object(Person) which have an UIImage, NSMutableArray and NSString objects. Currently I am able to encode and decode the NSString objects and archive Person to in NSUserDefault. Everything works fine except for UIImage and NSArray.
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
self.userName = [aDecoder decodeObjectForKey:#"userName"]; //NSString
self.profileImage = [aDecoder decodeObjectForKey:#"profileImage"]; //UIImage
self.uplodedVideoArray = [aDecoder decodeObjectForKey:#"uplodedVideoArray"]; //NSMutableArray
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.userName forKey:#"userName"]; //NSString
[aCoder encodeObject:self.profileImage forKey:#"profileImage"]; //UIImage
[aCoder encodeObject:self.uplodedVideoArray forKey:#"uplodedVideoArray"]; //NSMutableArray
}
-(void)archivePerson
{
NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:[Person sharedInstance]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:encodedObject forKey:#"Person"];
[defaults synchronize];
}
-(Person *)unarchivePerson
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *encodedObject = [defaults objectForKey:#"Person"];
Person *person = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject];
return person;
}
You can only store certain types of objects to NSUserDefaults, the same types that can be written to plist files.
(See here https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PropertyLists/AboutPropertyLists/AboutPropertyLists.html )
So you cannot store an image there. The reason you're having problems with the array is that collections (arrays/dictionaries) are only plist compatible if they contain plist compatible objects only. Your best approach is to save your image/video files seperately and then write the URL (as String/NSString) to NSUserDefaults. Best

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"];

How to save fields correctly with NSUserDefaults?

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"]];
}

Why doesn't NSUserDefault work with my dictionary object? [duplicate]

This question already has answers here:
How to store custom objects in NSUserDefaults
(7 answers)
Closed 9 years ago.
I created an object for a make believe user that stores the username and password, I then put the object in a dictionary. Now I'm trying to store the dictionary using NSUserDefault but its not letting me. I understand its best not to use NSUserDefault to store user data but this is just beginner stuff I'm trying to learn.
/**interface file **/
#import "newUser.h"
#interface BWViewController : UIViewController
{
IBOutlet UITextField *userNameField;
IBOutlet UITextField *passwordField;
IBOutlet UILabel * loginStatus;
}
#property (nonatomic, copy) NSDictionary * aUser;
-(IBAction)signUpButton;
#end
/**implementation file**/
#interface BWViewController ()
#end
#implementation BWViewController
#synthesize aUser;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
-(IBAction) signUpButton
{
newUser * firstUser = [[newUser alloc] init];
firstUser.userName = userNameField.text;
firstUser.password = passwordField.text;
NSLog(#"%#", firstUser.userName); /**for testing**/
NSLog(#"%#", firstUser.password); /**for testing**/
aUser = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:firstUser, nil] forKeys:[NSArray arrayWithObjects:userNameField.text, nil]];
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:aUser forKey:userNameField.text];
[defaults synchronize];
loginStatus.text = #"Thanks for signing up!";
}
The better way to do that is store two user defaults one for username and one for password:
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:firstUser.userName forKey:#"USERNAME"];
[defaults setObject:firstUser.password forKey:#"PASSWORD"];
[defaults synchronize];
It doesn't work because you want to store nsdictionary with nsarray with custom object (firstUser) but NSUserDefaults doesn't allow you to store custom object.
Hope this help
//Extended
By saveForKey: and newUseFromKey: I mean something like that:
+(void)saveForKey:(NSString*)key
{
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.userName forKey:[NSString stringWithFormat:#"%#_USERNAME", key]];
[defaults setObject:self.password forKey:[NSString stringWithFormat:#"%#_PASSWORD", key]];
//.... other properties
[defaults synchronize];
}
+(newUser)newUseFromKey:(NSString*)key
{
newUser * user = [[newUser alloc] init];
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
user.userName = [defaults objectForKey:[NSString stringWithFormat:#"%#_USERNAME", key]];
user.password = [defaults objectForKey:[NSString stringWithFormat:#"%#_PASSWORD", key]];
//.... other properties
return user;
}
It's good solution if you don't store too many newUser object and if they don't have too many properties.
The best option is put all of your object to array/dictionary (It's up to you, there is no best option between this two) and save it to file. Just remember that if you want to save custom object to file system you have to implement NSCoding protocol.

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"]);