当前位置: 移动技术网 > IT编程>移动开发>IOS > iOS数据持久化——属性列表和归档

iOS数据持久化——属性列表和归档

2018年11月25日  | 移动技术网IT编程  | 我要评论

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);

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

  • ios uicollectionview实现横向滚动

    现在使用卡片效果的app很多,之前公司让实现一种卡片效果,就写了一篇关于实现卡片的文章。文章最后附有demo实现上我选择了使用uicollectionview ... [阅读全文]
  • iOS UICollectionView实现横向滑动

    本文实例为大家分享了ios uicollectionview实现横向滑动的具体代码,供大家参考,具体内容如下uicollectionview的横向滚动,目前我使... [阅读全文]
  • iOS13适配深色模式(Dark Mode)的实现

    iOS13适配深色模式(Dark Mode)的实现

    好像大概也许是一年前, mac os系统发布了深色模式外观, 看着挺刺激, 时至今日用着也还挺爽的终于, 随着iphone11等新手机的发售, ios 13系统... [阅读全文]
  • ios 使用xcode11 新建项目工程的步骤详解

    ios 使用xcode11 新建项目工程的步骤详解

    xcode11新建项目工程,新增了scenedelegate这个类,转而将原appdelegate负责的对ui生命周期的处理担子接了过来。故此可以理解为:ios... [阅读全文]
  • iOS实现转盘效果

    本文实例为大家分享了ios实现转盘效果的具体代码,供大家参考,具体内容如下demo下载地址: ios转盘效果功能:实现了常用的ios转盘效果,轮盘抽奖效果的实现... [阅读全文]
  • iOS开发实现转盘功能

    本文实例为大家分享了ios实现转盘功能的具体代码,供大家参考,具体内容如下今天给同学们讲解一下一个转盘选号的功能,直接上代码直接看viewcontroller#... [阅读全文]
  • iOS实现轮盘动态效果

    本文实例为大家分享了ios实现轮盘动态效果的具体代码,供大家参考,具体内容如下一个常用的绘图,主要用来打分之类的动画,效果如下。主要是ios的绘图和动画,本来想... [阅读全文]
  • iOS实现九宫格连线手势解锁

    本文实例为大家分享了ios实现九宫格连线手势解锁的具体代码,供大家参考,具体内容如下demo下载地址:效果图:核心代码://// clockview.m// 手... [阅读全文]
  • iOS实现卡片堆叠效果

    本文实例为大家分享了ios实现卡片堆叠效果的具体代码,供大家参考,具体内容如下如图,这就是最终效果。去年安卓5.0发布的时候,当我看到安卓全新的material... [阅读全文]
  • iOS利用余弦函数实现卡片浏览工具

    iOS利用余弦函数实现卡片浏览工具

    本文实例为大家分享了ios利用余弦函数实现卡片浏览工具的具体代码,供大家参考,具体内容如下一、实现效果通过拖拽屏幕实现卡片移动,左右两侧的卡片随着拖动变小,中间... [阅读全文]
验证码:
移动技术网