iOS开发笔记(十七):持久化方案之 NSUserDefaults

对于应用来说,每个用户都有自己的独特偏好设置,而好的应用会让用户根据喜好选择合适的使用方式,把这些偏好记录在应用包的 plist 文件中,通过 NSUserDefaults 类来访问,这是 NSUserDefaults 的常用姿势。如果有一些设置你希望用户即使升级后还可以继续使用,比如玩游戏时得过的最高分、喜好和通知设置、主题颜色甚至一个用户头像,那么你可以使用 NSUserDefaults 来存储这些信息。

具体来说 NSUserDefaults 是 iOS 系统提供的一个单例类(iOS 提供了若干个单例类),通过类方法 standardUserDefaults 可以获取 NSUserDefaults 单例。如:

NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
复制代码

NSUserDefaults 单例以 key-value 的形式存储了一系列偏好设置,key 是名称,value 是相应的数据。存/取数据时可以使用方法 objectForKey: 和 setObject:forKey: 来把对象存储到相应的 plist 文件中,或者读取,既然是 plist 文件,那么对象的类型则必须是 plist 文件可以存储的类型,如下:

  • NSData
  • NSString
  • NSNumber
  • NSDate
  • NSArray
  • NSDictionary

而如果需要存储 plist 文件不支持的类型,比如自定义对象和图片,可以先将其归档为 NSData 类型,再存入 plist 文件,需要注意的是,即使对象是 NSArray 或 NSDictionary,他们存储的类型也应该是以上范围包括的。下面介绍用法。

1.用法

1.1 plist 支持的类型

//获取单例
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];

NSString *password = [NSString stringWithFormat:@"1234567"];
[user setObject:password forKey:@"password"];//存

NSString *passwordCopy = [user objectForKey:@"password"];//取
NSLog(@"password - %@",passwordCopy);

//数组
NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2",@"3", nil];
[user setObject:array forKey:@"array"];//存

NSMutableArray *arrayCopy = [NSMutableArray arrayWithArray:[user objectForKey:@"array"]];//取
[arrayCopy addObject:@"4"];
NSLog(@"array - %@",arrayCopy);
复制代码

1.1 plist 不支持的类型

plist 不支持的类型需要先将其归档为 NSData 类型,再存入 plist 文件。

NSUserDefaults *user = [NSUserDefaults standardUserDefaults];

//图片
UIImage *image =[UIImage imageNamed:@"somename"];
NSData *imageData = UIImageJPEGRepresentation(image, 100);//把image归档为NSData
[user setObject:imageData forKey:@"image"];//存

[defaults synchronize];//方法synchronise是为了强制存储

NSData *imageData = [defaults dataForKey:@"image"];//取
UIImage *image = [UIImage imageWithData:imageData];

//对象
Student *student = [[Student alloc] init];
student.name = @"Tom";
student.sex = @"male";
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:student];//归档为NSData	
[user setObject:data forKey:@"data"];//存

NSData *dataCopy = [user objectForKey:@"data"];//取
Student *studentCopy = [NSKeyedUnarchiver unarchiveObjectWithData:dataCopy];
NSLog(@"name - %@,sex - %@",studentCopy.name,studentCopy.sex);
复制代码

注意

NSUserDefaults 设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了 set 方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用 synchornize 方法强制写入。

2.拾遗

简便方法存取不同类型数据

其实,NSUserDefaults 提供了若干简便方法可以存储某些常用类型的值,这将使某些值的设置更简单。例如 :

- setBool:forKey://这里又支持BOOL类型了
- setFloat:forKey:
- setInteger:forKey:
- setDouble:forKey:
- setURL:forKey://这里又支持NSURL类型了
复制代码

对应的取值方法也有。

NSUserDefaults 数据库中其实是由多个层级的域组成的,当你读取一个键值的数据时,NSUserDefaults 从上到下透过域的层级寻找正确的值,不同的域有不同的功能,有些域是可持久的,有些域则不行。

  • 应用域 :是最重要的域,它存储着你 app 通过 set:forKey:添加的设置。
  • 注册域 :仅有较低的优先权,只有在应用域没有找到值时才从注册域去寻找。
  • 全局域 :存储着系统的设置。
  • 语言域 :包括地区、日期等。
  • 参数域 :有最高优先权。

registerDefaults

NSUserDefaults 还提供了一个 registerDefaults 方法,通常在 appDelegate 的 didFinishLaunchingWithOptions 里调用

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  

	NSDictionary *defaultValues = [NSDictionary dictionaryWithObjectsAndKeys: @"blue", @"color",nil];   
	[[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues];  
  
	return YES;  
}  
复制代码

registerDefaults 方法调用时会检查 NSUserDefaults 里是否已经存在了相同的 key,如果有则不会把其覆盖。举个例子 :

  1. 当第一次 run 上面的 app 时,"color" = "blue" 会写入 NSUserDefaults 里。

  2. 然后你的 app 调用了

     [[NSUserDefaults standardUserDefaults] setObject:@"red" forKey:@"color"];
    复制代码

    这时 NSUserDefaults 里 "color" = "red"。

  3. 退出 app 并重进,registerDefaults 方法还是会被调用,但它检查到 "color" key 已经存在,就不会把它写入 NSUserDefaults 中,这时 NSUserDefaults 里 "color" = "red"。

原因跟上面的联系起来就很容易理解了。registerDefaults 方法会存储进注册域,应用域没有值时才会从通过 registerDefaults 方法取值。

其他方法

// 同步对共享对象的任何更改默认用户和从内存中释放它。
+ (void)resetStandardUserDefaults;
//返回一个和defaultName关联的BOOL值,不存在则返回NO
- (BOOL)boolForKey:(NSString *)defaultName;
// 返回与指定键相关联的数组。
- (NSArray *)arrayForKey:(NSString *)defaultName
// 返回一个字典,它包含在搜索列表中的域的所有键值对联盟。(NSData,NSString, NSNumber,NSDate,NSArray,或 NSDictionary)
- (NSDictionary *)dictionaryRepresentation
// 消除了在标准应用程序域指定的默认键值。
- (void)removeObjectForKey:(NSString *)defaultName
// 删除指定的从用户的默认持久域的内容。
- (void)removePersistentDomainForName:(NSString *)domainName
// 设置为指定的字典持久域。
- (void)setPersistentDomain:(NSDictionary *)domain forName:(NSString *)domainName
// 设置为指定的字典挥发性域。
- (void)setVolatileDomain:(NSDictionary *)domain forName:(NSString *)domainName
// 返回NSUserDefaults对象初始化的用户帐户的默认为指定的。
- (id)initWithUser:(NSString *)username
复制代码

3.参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值