IOS 数据存储详解及实例代码
ios应用数据存储的常用方式
- xml属性列表(plist)归档
- preference(偏好设置)
- nskeyedarchiver归档(nscoding)
- sqlite3
- core data
1. xml属性列表(plist)归档
每个ios应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离。应用必须待在自己的沙盒里,其他应用不能访问该沙盒。
应用沙盒结构分析:
应用程序包:包含了所有的资源文件和可执行文件
documents:保存应用运行时生成的需要持久化的数据,itunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录
tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。itunes同步设备时不会备份该目录
library/caches:保存应用运行时生成的需要持久化的数据,itunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据
library/preference:保存应用的所有偏好设置,ios的settings(设置)应用会在该目录中查找应用的设置信息。itunes同步设备时会备份该目录
应用沙盒目录的常见获取方式
沙盒根目录:nsstring *home = nshomedirectory(); documents:(2种方式) 1. 利用沙盒根目录拼接”documents”字符串 //不建议采用,因为新版本的操作系统可能会修改目录名 nsstring *home = nshomedirectory(); nsstring *documents = [home stringbyappendingpathcomponent:@"documents"]; 2. 利用nssearchpathfordirectoriesindomains函数 // nsuserdomainmask 代表从用户文件夹下找 // yes 代表展开路径中的波浪字符“~” nsarray *array = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, no); // 在ios中,只有一个目录跟传入的参数匹配,所以这个集合里面只有一个元素 nsstring *documents = [array objectatindex:0]; tmp: nsstring *tmp = nstemporarydirectory(); library/caches: 跟documents类似的2种方法: 1. 利用沙盒根目录拼接”caches”字符串 2. 利用nssearchpathfordirectoriesindomains函数(将函数的第2个参数改为:nscachesdirectory即可) library/preference: 通过nsuserdefaults类存取该目录下的设置信息
属性列表
属性列表是一种xml格式的文件,拓展名为plist
如果对象是nsstring、nsdictionary、nsarray、nsdata、nsnumber等类型,就可以使用writetofile:atomically:方法直接将对象写到属性列表文件中
如:将一个nsdictionary对象归档到一个plist属性列表中
/ /获取路径 nsstring *path = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes)[0]; path = [path stringbyappendingpathcomponent:@"save.plist"]; / /将数据封装成字典 //不能存储对象 nsmutabledictionary *dict = [nsmutabledictionary dictionary]; [dict setobject:@"小黄" forkey:@"name"]; [dict setobject:@"12345678" forkey:@"phone"]; [dict setobject:@"24" forkey:@"age"]; // 将字典持久化到documents/save.plist文件中 [dict writetofile:path atomically:yes];
恢复nsdictionary
读取属性列表,恢复nsdictionary对象 // 读取documents/save.plist的内容,实例化nsdictionary nsdictionary *dict = [nsdictionary dictionarywithcontentsoffile:path]; nslog(@"name:%@", [dict objectforkey:@"name"]); nslog(@"phone:%@", [dict objectforkey:@"phone"]); nslog(@"age:%@", [dict objectforkey:@"age"]);
**nsdictionary—(writetofile:atomically:)—-> save.plist
(属性列表文件)**save.plist(属性列表文件)—(dictionarywithcontentsoffile:)—> nsdictionary
2. preference(偏好设置)
很多ios应用都支持偏好设置,比如保存用户名、密码、字体大小等设置,ios提供了一套标准的解决方案来为应用加入偏好设置功能
每个应用都有个nsuserdefaults实例,通过它来存取偏好设置
//比如,保存用户名、字体大小、是否自动登录 nsuserdefaults *defaults = [nsuserdefaults standarduserdefaults]; [defaults setobject:@"mr.zk" forkey:@"username"]; [defaults setfloat:18.0f forkey:@"text_size"]; [defaults setbool:yes forkey:@"auto_login"];
//读取上次保存的设置 nsuserdefaults *defaults = [nsuserdefaults standarduserdefaults]; nsstring *username = [defaults stringforkey:@"username"]; float textsize = [defaults floatforkey:@"text_size"]; bool autologin = [defaults boolforkey:@"auto_login"];
注意:userdefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘应用程序就终止了。出现以上问题,可以通过调用synchornize方法强制写入
[defaults synchornize];
3. nskeyedarchiver归档(nscoding)
nskeyedarchiver
如果对象是nsstring、nsdictionary、nsarray、nsdata、nsnumber等类型,可以直接用
nskeyedarchiver
进行归档和恢复不是所有的对象都可以直接用这种方法进行归档,只有遵守了
nscoding
协议的对象才可以
* nscoding协议有2个方法:*
encodewithcoder:
每次归档对象时,都会调用这个方法。一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用encodeobject:forkey:方法归档实例变量
initwithcoder:
每次从文件中恢复(解码)对象时,都会调用这个方法。一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeobject:forkey方法解码实例变量
归档一个nsarray对象到documents/array.data
nsstring *path = nssearchpathfordirectoriesindomains(nscachesdirectory, nsuserdomainmask, yes)[0]; path = [path stringbyappendingpathcomponent:@"array.data"]; nsarray *array = [nsarray arraywithobjects:@”a”,@”b”,nil]; [nskeyedarchiver archiverootobject:array tofile:path];
恢复(解码)nsarray对象
nsarray *array = [nskeyedunarchiver unarchiveobjectwithfile:path];
nsarray—(archiverootobject:tofile:)—-> array.data
array.data—(unarchiveobjectwithfile:)—> nsarray
nskeyedarchiver-归档person对象(person.h) @interface person : nsobject<nscoding> @property (nonatomic, strong) nsstring *name; @property (nonatomic, assign) int age; @property (nonatomic, assign) float height; @end
@implementation person - (void)encodewithcoder:(nscoder *)encoder { [encoder encodeobject:self.name forkey:@"name"]; [encoder encodeint:self.age forkey:@"age"]; [encoder encodefloat:self.height forkey:@"height"]; } - (id)initwithcoder:(nscoder *)decoder { self.name = [decoder decodeobjectforkey:@"name"]; self.age = [decoder decodeintforkey:@"age"]; self.height = [decoder decodefloatforkey:@"height"]; return self; } @end
//归档(编码) person *person = [[[person alloc] init] autorelease]; person.name = @"zk"; person.age = 24; person.height = 1.73f; [nskeyedarchiver archiverootobject:person tofile:path]; //恢复(解码) person *person = [nskeyedunarchiver unarchiveobjectwithfile:path];
如果父类也遵守了nscoding协议,请注意:
应该在encodewithcoder:方法中加上
[super encodewithcode:encode];
确保继承的实例变量也能被编码,
即也能被归档应该在initwithcoder:方法中加上
self = [super initwithcoder:decoder];
确保继承的实例变量也能被解码,即也能被恢复
nsdata
使用archiverootobject:tofile:方法可以将一个对象直接写入到一个文件中,但有时候可能想将多个对象写入到同一个文件中,那么就要使用nsdata来进行归档对象
nsdata可以为一些数据提供临时存储空间,以便随后写入文件,或者存放从磁盘读取的文件内容。可以使用[nsmutabledata data]创建可变数据空间
//归档(编码) // 新建一块可变数据区 nsmutabledata *data = [nsmutabledata data]; // 将数据区连接到一个nskeyedarchiver对象 nskeyedarchiver *archiver = [[[nskeyedarchiver alloc] initforwritingwithmutabledata:data] autorelease]; // 开始存档对象,存档的数据都会存储到nsmutabledata中 [archiver encodeobject:person1 forkey:@"person1"]; [archiver encodeobject:person2 forkey:@"person2"]; // 存档完毕(一定要调用这个方法) [archiver finishencoding]; // 将存档的数据写入文件 [data writetofile:path atomically:yes];
利用归档实现深复制
//恢复(解码) // 从文件中读取数据 nsdata *data = [nsdata datawithcontentsoffile:path]; // 根据数据,解析成一个nskeyedunarchiver对象 nskeyedunarchiver *unarchiver = [[nskeyedunarchiver alloc] initforreadingwithdata:data]; person *person1 = [unarchiver decodeobjectforkey:@"person1"]; person *person2 = [unarchiver decodeobjectforkey:@"person2"]; // 恢复完毕 [unarchiver finishdecoding];
person1—(archiveddatawithrootobject:)—>nsdata—(unarchiveobjectwithdata:)—>person2
4. sqlite3(之后补充)
5. core data(之后补充)
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!