在iPhone中,想要在本地存储数据有三种方法:数据库,文件,还有NSUSerDefault,NSUserDefault是系统自定义的类,可以随时在需要使用的地方声明对象然后存储数据。无需添加协议。NSUserDefault与文件和数据库相比也有自身的限制,能存储的文件内容较少,不能放置大容量数据。
声明方法很简单:
NSUserDefaults *myDefault =[NSUserDefaults standardUserDefaults];
然后可以用setObject:forKey:方法往NSUserDefault中存数据,objectForKey:方法取数据,例如:
- (void)viewDidLoad
{
NSUserDefaults *myDefault =[NSUserDefaults standardUserDefaults];//声明
NSString *dataString =@"helloWorld";
[myDefault setObject:dataString forKey:@"data"];//存数据
NSString *dataStringSec = [[NSUserDefaults standardUserDefaults] objectForKey:@"data"];//取数据
NSLog(@"%@",dataStringSec);
}
NSUserDefault可以存放非自定义类型数据,只支持
:NSString, NSNumber, NSDate, NSArray, NSDictionary。也许会有个疑问,我把数据自定义数据放在数组里存进去不就可以了吗?答案是否定的。要存放自定义的数据,必须经过NSCoder对象编码和解码。
NSCoder编码和解码是cocoa自身的一种机制,当你的数据要写入硬盘中去的时候,数据就会进行编码变成二进制文件写入硬盘中,当你要读出硬盘上的数据时,数据就会进行解码,这两个过程分别是序列化和反序列化。因为非自定义类型数据例如NSString,NSData等等自身已经隐含了<NSCoding>协议,即进行了对象的序列化与反序列化,我们可以直接把数据存放到NSUserDefaults与plist文件中。所以我们现在要做的事情就是给自定义的类添加NSCoder协议。
首先声明了一个People类
People.h
#import <Foundation/Foundation.h>
@interface People : NSObject<NSCoding>
@property(strong,nonatomic)NSString *name;
@property(assign,nonatomic)NSInteger age;
@property(assign,nonatomic)Boolean isMale;
-(void) initwithname:(NSString *)n andage:(NSInteger)a andisMale:(Boolean)i;
@end
People.m
#import "People.h"
@implementation People
@synthesize name;
@synthesize age;
@synthesize isMale;
-(void) initwithname:(NSString *)n andage:(NSInteger)a andisMale:(Boolean)i{
self.name=n;
self.age=a;
self.isMale=i;
}
-(void)encodeWithCoder:(NSCoder *)aCoder//编码
{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
[aCoder encodeBool:self.isMale forKey:@"isMale"];
}
- (id)initWithCoder:(NSCoder *)aDecoder//解码
{
self = [super init];
if (self)
{
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntegerForKey:@"age"];
self.isMale =[aDecoder decodeBoolForKey:@"isMale"];
}
return self;
}
@end
一般的NSString用到的是encodeObject:ForKey:方法,NSInteger 要用到encodeInteger:forKey:方法,而boolean/BOOL则要用到encodeBool:ForKey:方法,要注意区分。
ViewController.h#import <UIKit/UIKit.h>
#import "People.h"
@interface ViewController : UIViewController<NSCoding>
@property(strong,nonatomic)People *people;
@end
最重要的是要加入<NSCoding>委托
ViewController.m
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize people;
- (void)viewDidLoad
{
people=[[People alloc]init];
[people initwithname:@"change" andage:20 andisMale:true];
NSData *archivePeopleData = [NSKeyedArchiver archivedDataWithRootObject:people];
NSUserDefaults *myDefault =[NSUserDefaults standardUserDefaults];
[myDefault setObject:archivePeopleData forKey:@"people"];
People *Secpeople =[[People alloc]init];
NSData *myEncodedObject = [[NSUserDefaults standardUserDefaults] objectForKey:@"people"];
Secpeople = [NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject];
NSLog(@"name=%@,age=%d,isMale=%@",Secpeople.name,Secpeople.age,Secpeople.isMale?@"true":@"false");
}
@end
其中要通过NSData作为载体传输数据,即使在自定义类中做好了NSCoding,直接把自定义类加进NSUserDefaults中还是会报错
NSData *archivePeopleData = [NSKeyedArchiver archivedDataWithRootObject:people];
Secpeople = [NSKeyedUnarchiver unarchiveObjectWithData: myEncodedObject];
这两句分别是编码和解码的过程。
至此,关于NSUSerDefaults的介绍就结束了。