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