IOS开发中数据持久化的几种方法--NSUserDefaults
IOS开发中数据持久化的几种方法--NSUserDefaults
IOS 开发中,经常会遇到需要把一些数据保存在本地的情况,那么这个时候我们有以下几种可以选择的方案:
一、使用NSUserDefault是最简单直接的一个办法:
1)保存数据:
1 // 实例化一个NSUserDefaults单例对象 2 NSUserDefaults *user = [NSUserDefaults standardUserDefaults]; 3 // 把一个数组array保存在key为allContact的键值对里 4 [user setObject:array forKey:@"allContact"]; 5 // 直接写入硬盘 6 [user synchronize];
2)读取数据:
1 // 实例化一个NSUserDefaults单例对象 2 NSUserDefaults *user = [NSUserDefaults standardUserDefaults]; 3 // 把保存在里面的array根据key为allContact拿出来 4 NSArray *dataarray = [user objectForKey:@"allContact"];
注意事项:
在苹果的官方文档有明确说明:
也就是说,只能存入 NSData
, NSString
, NSNumber
, NSDate
, NSArray
, or NSDictionary
. For NSArray
and NSDictionary
objects, their contents must be property list objects.这些对象,而且(. For NSArray
and NSDictionary
objects, their contents must be property list objects.)比如数组,字典中存的元素也只能是以上这些对象的内容,那如何把自定义的一个比较复杂的类的实例对象使用NSUserDefaults保存呢?方法如下:
以一个手机联系人类myContact为例说明:
1)在myContact.h文件中让类遵守NSCoding协议:
1 // 2 // myContact.h 3 // 老年人电话本 4 // 5 // Created by mac on 16/5/3. 6 // Copyright © 2016年 mzw. All rights reserved. 7 // 8 9 #import <Foundation/Foundation.h> 10 11 //要使用单例NSUserDefault来存储自定义对象,首先要让自定义的对象遵守NSCoding协议 12 @interface myContact : NSObject<NSCoding> 13 14 @property(nonatomic, copy)NSString *firstname; 15 @property(nonatomic, copy)NSString *lastname; 16 @property(nonatomic, copy)NSString *phoneNumber; 17 @property(nonatomic, copy)NSData *photo; 18 @property(nonatomic, copy)NSString *identify; 19 @property(nonatomic, assign)BOOL emergency; 20 21 @end
2)在myContact.m文件中实现两个方法:encodeWithCoder 和 initWithCoder方法
1 // 2 // myContact.m 3 // 老年人电话本 4 // 5 // Created by mac on 16/5/3. 6 // Copyright © 2016年 mzw. All rights reserved. 7 // 8 9 #import "myContact.h" 10 11 @implementation myContact 12 13 @synthesize firstname; 14 @synthesize lastname; 15 @synthesize phoneNumber; 16 @synthesize photo; 17 @synthesize identify; 18 @synthesize emergency; 19 20 -(void)encodeWithCoder:(NSCoder *)aCoder{ 21 22 [aCoder encodeObject:self.firstname forKey:@"firstname"]; 23 [aCoder encodeObject:self.lastname forKey:@"lastname"]; 24 [aCoder encodeObject:self.phoneNumber forKey:@"phoneNumber"]; 25 [aCoder encodeObject:self.photo forKey:@"photo"]; 26 [aCoder encodeObject:self.identify forKey:@"identify"]; 27 [aCoder encodeBool:self.emergency forKey:@"emergency"];//注意对于布尔类型的不能使用encodeObject,而要对应的使用encodeBool。 28 } 29 30 -(id)initWithCoder:(NSCoder *)aDecoder{ 31 32 if (self = [super init]) { 33 34 self.firstname = [aDecoder decodeObjectForKey:@"firstname"]; 35 self.lastname = [aDecoder decodeObjectForKey:@"lastname"]; 36 self.phoneNumber = [aDecoder decodeObjectForKey:@"phoneNumber"]; 37 self.photo = [aDecoder decodeObjectForKey:@"photo"]; 38 self.identify = [aDecoder decodeObjectForKey:@"identify"]; 39 self.emergency = [aDecoder decodeBoolForKey:@"emergency"];//同理此处要对应的使用decodeBoolForKey。 40 } 41 return self; 42 }
3)完成以上两步,我们就可以通过NSUserDefaults来保存myContact的实例对象了:(以下程序段既涉及到读取,又涉及到追加内容后保存)
1 // 属性值赋值完成后就可以使用NSKeyedArchiver把对象mycontact1打包为一个NSData对象 2 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:mycontact1]; 3 // 创建并初始化一个NSUserDefaults单例对象 4 NSUserDefaults *user = [NSUserDefaults standardUserDefaults]; 5 // 先读取user之前存进去的allContact所对应的值(是一个不可变的数组),然后因为我们要给这个数组追加一个联系人的打包后的NSData数据,所以要把这个数组转换成为一个可变数组。 6 NSMutableArray *contactarray = [NSMutableArray arrayWithArray:[user objectForKey:@"allContact"]]; 7 // 把之前打包好的联系人mycontact1的NSData数据追加到可变数组contactarray中 8 [contactarray addObject:data]; 9 // 再把这个可变数组转换为一个不可变数组 10 NSArray *array = [NSArray arrayWithArray:contactarray]; 11 // 使用相同的key值保存新的array,之前allContact对应的值被替换 12 [user setObject:array forKey:@"allContact"]; 13 // 直接写入硬盘 14 [user synchronize];
注意:通过NSUserDefaults保存的数据是全局的,这也为我们提供了一个管理全局变量的手段,比如在页面A保存了一些数据,在其他很多页面都要用到,那我们可以通过单例来保存,这样就可以在不同的页面中通过同个NSUserDefaults的key值去读取对应的内容。但这样的操作要注意,保存的数据一定是不可变的,不能是可变的数组、可变字符串、可变字典等,否则程序会产生不可预期的错误。