iOS数据持久化——属性列表和归档
ios数据持久化的方式分为三种
属性列表 (自定义的property list 、nsuserdefaults)
归档 (nskeyedarchiver)
(sqlite、core data、第三方类库等)
本文只介绍:属性列表和归档
一. 属性列表
plist一般用于存储dictionary、array、boolean、data、date、number、string这些类型的数据,但boolean、data、date、number、string类型的数据一般不直接存入plist文件中,因为plist文件有分层的概念,一般用nsdictionary或nsarray作为容器,再把其他数据类型装入,最后把容器存入plist文件。plist文件不能直接存储自定义的类,需要进行转化成上述的数据类型,才能存储。
(一). 数据的简单存储
nsdictionary或nsarray使用writetofile:atomically:方法,会默认存储到plist文件
// 获取沙盒中documents目录的路径 nsstring *documentspath = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes)[0]; // 拼接路径 nsstring *someobjpath = [documentspath stringbyappendingpathcomponent:@"someobj.plist"]; // 要写入文件的数组 nsarray *someobj = @[@"aaa",@"bbb",@999,@'a',@[@{@"name":@"小明"}]]; // 把数组写入plist文件 // 第一个参数是文件名,第二个参数为是否使用辅助文件,如果为yes,则先写入到一个辅助文件,然后辅助文件再重新命名为目标文件, // 如果为no,则直接写入到目标文件 [someobj writetofile:someobjpath atomically:yes];
(二). nsfilemanager常用的文件管理
创建目录 createdirectoryatpath:
创建文件 createfileatpath:
删除某个文件 removeitematpath:
检查某个文件是否存在 fileexistsatpath:
检查文件是否可读 isreadablefileatpath:
是否可写:iswritablefileatpath:
取得文件属性 fileattributesatpath:
改变文件属性changeattributesatpath:
从path代表的文件中读取数据:contentsatpath
移动文件movepath:topath:handler:
复制文件copypath:topath:handler:
// 1. 在沙盒里新建目录,再在目录里新建文件夹 // 创建一个文件管理器 nsfilemanager *filemanager = [nsfilemanager defaultmanager]; // 获取沙盒下的documents路径 nsstring *documentspath = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes).firstobject; // 拼接路径 nsstring *newfilepath = [documentspath stringbyappendingpathcomponent:@"newfile"]; // 创建新目录 [filemanager createdirectoryatpath:newfilepath withintermediatedirectories:yes attributes:nil error:nil]; // 读写数据一 // 2. 向filenew.plist写入数据 // 把路径改变到新路径下 [filemanager changecurrentdirectorypath:[newfilepath stringbyexpandingtildeinpath]]; // 创建filenew.plist文件 [filemanager createfileatpath:@"filenew.plist" contents:nil attributes:nil]; // 写入数据 nsarray *dataarr = @[@[@100,@"study"],@{@"name":@"xiaoming"}]; // 拼接filenew.plist路径 nsstring *datapath = [newfilepath stringbyappendingpathcomponent:@"filenew.plist"]; // 把数组写入filenew.plist [dataarr writetofile:datapath atomically:yes]; // 3. 读取filenew.plist数据 nsarray *arrdata = [nsarray arraywithcontentsoffile:datapath]; nslog(@"%@",arrdata); // 读写数据二 // 使用nsmutabledata存储数据要记住存储的顺序,读取数据时要要根据那个顺序计算每个数据所处的位置 // 2. 向filename文件写入数据 // 待写入的数据 nsstring *datastr = @"new friend"; int dataint = 666; float datafloat = 3.14159f; // 拼接存储数据的路径 nsstring *datapath2 = [newfilepath stringbyappendingpathcomponent:@"filename"]; //创建数据缓冲 nsmutabledata *writerdata = [[nsmutabledata alloc] init]; //将字符串添加到缓冲中 [writerdata appenddata:[datastr datausingencoding:nsutf8stringencoding]]; //将其他数据添加到缓冲中 [writerdata appendbytes:&dataint length:sizeof(dataint)]; [writerdata appendbytes:&datafloat length:sizeof(datafloat)]; //将缓冲的数据写入到文件中 [writerdata writetofile:datapath2 atomically:yes]; // 3. 读取数据: // 读取filename文件中的数据 nsdata *readerdata = [nsdata datawithcontentsoffile:datapath2]; // 计算datastr在datastr的区间,并获取字 datastr = [[nsstring alloc] initwithdata:[readerdata subdatawithrange:nsmakerange(0, [datastr length])] encoding:nsutf8stringencoding]; // 计算dataint在datastr的区间,并获取 [readerdata getbytes:&dataint range:nsmakerange([datastr length], sizeof(dataint))]; // 计算datafloat在datastr的区间,并获取 [readerdata getbytes:&datafloat range:nsmakerange([datastr length] + sizeof(dataint), sizeof(datafloat))]; nslog(@"datastr:%@ dataint:%d datafloat:%f", datastr,dataint,datafloat); // 删除filename文件 [filemanager removeitematpath:@"filename" error:nil]; // 删除一个目录: // currentdirectorypath:当前目录 nslog(@"%@",filemanager.currentdirectorypath); [filemanager removeitematpath:filemanager.currentdirectorypath error:nil];
二. 偏好设置
(一). 知识点
偏好设置的本质还是plist文件存储,相对于plist文件存储来讲存储数据更快捷,不需要获取全路径。
偏好设置用来保存应用程序设置和属性、用户保存的数据,当用户再次打开程序或开机后这些数据仍然存在。
很多ios应用都支持偏好设置,比如保存用户名、密码、字体大小等设置,ios也提供了一套标准的解决方案来为应用加入偏好设置功能。 每个ios应用都有一个nsuserdefaults实例,它是一个单例对象,通过它来存取偏好设置,设置信息都是键值对的形式。 用userdefaults实例设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘,所以调用了set方法之后数据有可能还没有写入磁盘,如果应用程序突然终止了,数据有可能写入不成功。 偏好设置是专门用来保存应用程序的配置信息的, 一般情况不要在偏好设置中保存其他数据。 如果利用的偏好设置来存储数据, 默认就是存储在preferences文件夹下面的,偏好设置会将所有的数据都保存到同一个文件中。 偏好设置针对同一个关键字对应的对象或者数据,可以对它进行重写,重写之后关键字就对应新的对象或者数据,旧的对象或者数据会被自动清理。 使用偏好设置对数据进行保存之后, 它保存到系统的时间是不确定的,会在将来某一时间点自动将数据保存到preferences文件夹下面,如果需要即刻将数据存储,可以使用[defaults synchronize];强制写入偏好设置文件。 ios7之后,如果不写[defaults synchronize];,数据也会同步存储。(二). 具体使用
nsuserdefaults *userdefaults = [nsuserdefaults standarduserdefaults]; [userdefaults setvalue:@"小明" forkey:@"name"]; [userdefaults setvalue:@"男" forkey:@"sex"]; [userdefaults setvalue:@"学生" forkey:@"work"]; // 写入磁盘 [userdefaults synchronize]; nslog(@"%@",[userdefaults objectforkey:@"name"]); nslog(@"%@",[userdefaults objectforkey:@"sex"]); nslog(@"%@",[userdefaults objectforkey:@"work"]);
三. 归档与解档
(一). 知识点
归档又名序列化,把对象转为字节码,以文件的形式存储到磁盘上;程序运行过程中或者重新打开程序时,可以通过解归档(反序列化)还原这些对象。 不是所有的对象都可以直接用这种方法进行归档,只有遵守了nscoding协议的对象才可以,如果对象是nsstring、nsdictionary、nsarray、nsdata、nsnumber等类型,可以直接用nskeyedarchiver进行归档。 每次归档对象时,都会调用encodewithcoder:方法;一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用encodeobject:forkey:方法归档实例变量。 每次从文件中恢复(解码)对象时,都会调用initwithcoder:方法;一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeobject:forkey方法解码实例变量。 归档和解归档可以用于少量数据的持久化存储和读取,且通过归档创建的文件是的缺点:在归档的形式来保存数据,只能一次性归档保存以及一次性解压,所以只能针对小量数据。而且对数据操作比较笨拙,即如果想改动数据的某一小部分,还是需要解压整个数据或者归档整个数据。
(二). 具体使用
归档方式有以下三种:
a. 对foundation框架中对象进行归档
b. 对自定义的内容进行归档
c. 对自定义的对象进行归档
1. 对foundation框架中对象进行归档
// 获取文件路径 nsstring *documentspath = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes)[0]; // 拼接路径 nsstring *datapath = [documentspath stringbyappendingpathcomponent:@"newdata.data"]; // 待归档的数据 nsarray *dataarr = @[@"天天",@"编程"]; // 归档 if ([nskeyedarchiver archiverootobject:dataarr tofile:datapath]) { nslog(@"archiver success !"); } // 解档 nsarray *data = [nskeyedunarchiver unarchiveobjectwithfile:datapath]; nslog(@"%@%@",data[0],data[1]);
2. 对自定义的内容进行归档
// 获取文件路径 nsstring *documentspath = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes)[0]; // 拼接路径 nsstring *datapath = [documentspath stringbyappendingpathcomponent:@"newdata.data"]; // 创建存储数据的nsdata对象 nsmutabledata *datam = [nsmutabledata data]; // 创建归档对象 nskeyedarchiver *archiver = [[nskeyedarchiver alloc] initforwritingwithmutabledata:datam]; // 添加归档内容 [archiver encodeobject:@"小明" forkey:@"name"]; [archiver encodeobject:@"男" forkey:@"sex"]; [archiver encodeinteger:19 forkey:@"age"]; // 完成归档内容 [archiver finishencoding]; // 写入磁盘 if ([datam writetofile:datapath atomically:yes]) { nslog(@"archiver success !"); } // 解档 // 获取数据 nsdata *data = [nsdata datawithcontentsoffile:datapath]; // 创建解档对象 nskeyedunarchiver *unarchiver = [[nskeyedunarchiver alloc] initforreadingwithdata:data]; // 解档 nsstring *name = [unarchiver decodeobjectforkey:@"name"]; nsstring *sex = [unarchiver decodeobjectforkey:@"sex"]; nsinteger age = [unarchiver decodeintforkey:@"age"]; nslog(@"%@ %@ %ld",name,sex,age);
3. 对自定义的对象进行归档
---------- person.h 文件 #import @interface person : nsobject @property (nonatomic,strong) nsstring *name; @property (nonatomic,strong) nsstring *sex; @property (nonatomic,assign) nsinteger age; @end ---------- person.m 文件 #import "person.h" @implementation person // 归档 - (void)encodewithcoder:(nscoder *)acoder { [acoder encodeobject:self.name forkey:@"name"]; [acoder encodeobject:self.sex forkey:@"sex"]; [acoder encodeinteger:self.age forkey:@"age"]; } // 解档 - (instancetype)initwithcoder:(nscoder *)adecoder { if (self = [super init]) { self.name = [adecoder decodeobjectforkey:@"name"]; self.sex = [adecoder decodeobjectforkey:@"sex"]; self.age = [adecoder decodeintegerforkey:@"age"]; } return self; } @end ---------- 对penson对象进行归档与解档 // 获取documents的路径 nsstring *documentpath = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes).firstobject; // 拼接路径 nsstring *path = [documentpath stringbyappendingpathcomponent:@"person.data"]; // person *per = [[person alloc] init]; per.name = @"xiaoming"; per.sex = @"男"; per.age = 20; // 归档 [nskeyedarchiver archiverootobject:per tofile:path]; // 解档 person *person = [nskeyedunarchiver unarchiveobjectwithfile:path]; nslog(@"%@",person.sex);
上一篇: Google移动设备工具优化站长网站篇
下一篇: 别让你妈妈把你拉出来了