问题
Hi I want to save and retrieve NSObject
class using NSUserDefaults
for that I wrote below code but I am getting exception like below
Terminating app due to uncaught exception '
NSInvalidArgumentException
', reason: 'Attempt to insert non-property list object for key DATA'
For saving :-
SavingBean*savingbean = [[SavingBean alloc]init];
[savingbean savingData:userName.text :passWord.text];
NSUserDefaults * defaults = [[NSUserDefaults alloc]init];
[defaults setObject:savingbean forKey:@"DATA"];
For retrieving:-
defaults = [[NSUserDefaults alloc]init];
savingbean = [defaults objectForKey:@"DATA"];
NSLog(@"Username is===>%@",savingbean.userName);
NSLog(@"Password is===>%@",savingbean.passWord);
ModelClas:-
.h file:-
#import <Foundation/Foundation.h>
@interface SavingBean : NSObject{
NSString *userName;
NSString *passWord;
}
@property(nonatomic, retain) NSString *userName;
@property(nonatomic, retain) NSString *passWord;
-(void)savingData :(NSString*)userName :(NSString*)password;
@end
.m file:-
#import "SavingBean.h"
@implementation SavingBean
@synthesize userName,passWord;
-(void)savingData :(NSString*)username :(NSString*)password{
userName = username;
passWord = password;
}
@end
回答1:
You can set object like this:
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:savingbean];
[currentDefaults setObject:data forKey:@"DATA"];
[currentDefaults synchronize];
and for get object like this:
NSData *data = [currentDefaults objectForKey:@"DATA"];
SavingBean *token = [NSKeyedUnarchiver unarchiveObjectWithData:data];
For Custom class you have to edit this methods in you bean class:
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:self.userName==nil?@"":self.userName forKey: @"userName"];
[encoder encodeObject:self.passWord==nil?@"":self.passWord forKey: @"passWord"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
self = [super init];
if(self)
{
self.userName = [decoder decodeObjectForKey: @"userName"];
self.passWord = [decoder decodeObjectForKey: @"passWord"];
}
return self;
}
Here is most voted similar answer. You can also get good stuff from there.
You can also use JSON Accelerator to create bean class. This is very simple and powerful tool.
回答2:
From good answer of Jayesh Thanki I tried sample from this question.I followed your coding.First I tried Save and Retrieve directly without encoder and decoder method.
For Save
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:savingbean];
[currentDefaults setObject:data forKey:@"DATA"];
[currentDefaults synchronize];
For Retrieve
NSData *data = [currentDefaults objectForKey:@"DATA"];
savingbean = [NSKeyedUnarchiver unarchiveObjectWithData:data];
Now it shows error
[SavingBean encodeWithCoder:]: unrecognized selector sent to instance 0x7fc65940fc40
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SavingBean encodeWithCoder:]: unrecognized selector sent to instance 0x7fc65940fc40'
Then I googled most of the answer say
The NSCoding protocol declares the two methods that a class must implement so that instances of that class can be encoded and decoded. This capability provides the basis for archiving (where objects and other structures are stored on disk) and distribution (where objects are copied to different address spaces).
encodeWithCoder
encodeWithCoder: instructs the object to encode its instance variables to the coder provided; an object can receive this method any number of times.
initWithCoder
initWithCoder: instructs the object to initialize itself from data in the coder provided; as such, it replaces any other initialization method and is sent only once per object.
Then I understood that we must implement the encodeWithCoder and inintWithCoder first in NSObject Class.After that only we should save and retrieve the data.
->encoder is an archiver object
->decoder is an unarchiver object
Now First we have to implement the encodeWithCoder and initWithCoder in SavingBean.m
- (void)encodeWithCoder:(NSCoder *)encoder
{
//Encode properties, other class variables, etc
[encoder encodeObject:@"AbhiRam" forKey:@"username"];
[encoder encodeObject:@"Test@123" forKey:@"password"];
}
- (id)initWithCoder:(NSCoder *)decoder
{
if((self = [super init]))
{
//decode properties, other class vars
userName = [decoder decodeObjectForKey:@"username"];
passWord = [decoder decodeObjectForKey:@"password"];
}
return self;
}
Then in ViewController.m
For Save
SavingBean *savingbean = [[SavingBean alloc]init];
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:savingbean];
[currentDefaults setObject:data forKey:@"DATA"];
[currentDefaults synchronize];
For Retrieve
NSData *data = [currentDefaults objectForKey:@"DATA"];
savingbean = [NSKeyedUnarchiver unarchiveObjectWithData:data];
Now when I run the application it does not show any error.It works fine now.
Why I give these things here is If anybody sees and tries this answer in some case they can get the error like above.So if they prefer two answer for this question they can very easily understand and get the solution very simply.
encodeWithCoder and initWithCoder of NSCoding
来源:https://stackoverflow.com/questions/38324609/how-to-save-and-retrieve-nsobject-class-using-nsuserdafaults-in-ios