iOS 一一 数据存储

来源:互联网 发布:淘宝装修设计是怎样的 编辑:程序博客网 时间:2024/04/30 05:28

iOS应用数据存储的常用方式

  • XML属性列表(plist) 归档
  • Preference(偏好设置)
  • NSKeyedArchiver归档(NSCoding)
  • SQLine3
  • Core Data

本篇博客只介绍前三种存储的常用方式.后两种后续会继续更新.


在讲述iOS数据存储之前.首先要了解什么是应用沙盒,以及沙盒中的目录结构.


应用沙盒

  • 每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录). 与其他文件系统隔离.应用必须待在自己的沙盒中,其他应用不可以访问该沙盒
  • 应用沙盒的文件系统目录.如下


注意:

我们可以通过NSLog(@"%@",NSHomeDirectory)来打印 应用程序沙盒的根目录


接下来针对以上目录,一一说明其有什么作用:

  • Documents: 保存应用运行时生成的需要持久化数据,iTunes同步设备时会备份该目录.

注意: 在Documents目录中不可以存放一些网络中下载的比较大的数据,因为iTunes会备份,如果存放一些比较大的数据,当应用程序打包上传appStore 会被审核不通过.

Documents目录 一般存放一些应用程序生成的一些数据


  • tmp: 保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除.应用程序没有运行时,系统可能会清除该目录下的文件.iTunes同步设备时不会备份该目录

  • Library/Caches: 保存应用运行时生成的需要持久化的数据,iTunes同步设备不会备份该目录.一般存储体积大、不需要备份的非重要的数据
注意:从网络中下载比较大的数据一般都放在Library/Caches目录下.

Library/Preference: 保存应用的所有偏好设置.iOS的应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录


应用沙盒目录的获取方式.

Plist存储:

plist 件存储 般都是存取字典和数组,直接写成plist 件,把它存到应 沙盒当

中.只有在ios当中才有plist存储,它是ios特有的存储 式. 

介绍完沙盒中的目录后.来讲解一下如何获取沙盒中的目录.

  • 沙盒的根目录: NSString *path = NSHomeDirectory();
比如要获取沙盒中Documents目录:
利用NSSearchPathForDirectoriesInDomains方法,这个方法返回是一个数组

iOS中,只有一个目录跟传入的参数匹配,所以这个集合里面只有一个元素

这个方法的参数:

arg1: NSDocumentDirectory 找到沙盒中目录(NSDocument,Caches)

arg2: NSUserDomainMask 搜索的范围(一般写NSUserDomainMask,沙盒的固定范围)

arg3: 是否展开路径(YES) 注: 在iOS开发中不识别~,在Mac平台可识别,所以必须要展开路径

NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];

在Documents目录下拼接一个文件名:

NSString *filePath = [path stringByAppendingPathComponent:@"data.plist"];

把字典数据保存到沙盒目录下的data.plist文件中

NSDictionary *dictArray = @{@"name" : @"ZY"};[dictArray writeToFile: filePath atomically: YES];

在这里.可以打印一下path,进入到沙盒的Documents目录下的data.plist文件中.数据是否已经保存在里面.



从沙盒目录下的文件中读取数据:

需要使用到dictionaryWithContentsOfFile:方法

    // 读取沙盒目录中的字典文件    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];    // 拿到字典文件名称    NSString *filePath = [path stringByAppendingPathComponent:@"data.plist"];    NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:filePath];    NSLog(@"%@",dict);


属性列表:

  • 属性列表是一种XML格式的文件,拓展名为plist
  • 如果对象是NSStringNSDictionaryNSArrayNSDataNSNumber等类型,就可以使用writeToFile:atomically:方法直接将对象写到属性列表文件中



Prference(偏好设置)
  • 许多iOS应用都支持偏好设置,比如保存用户名,密码,字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能.
  • 每个应用都有NSUserDefaults实例,通过它来存储偏好设置
  • 比如 保存用户名,字体大小,是否自动登录
  • 注意: NSUserDefaults 保存的也是一个plist文件

保存数据到沙盒中

    // Preferences 保存在library/Preferences目录中(plist文件)    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    [defaults setObject:@"ZY" forKey:@"name"];    [defaults setInteger:19 forKey:@"age"];        // 立刻写入到文件中(同步操作)    [defaults synchronize];        NSLog(@"%@",NSHomeDirectory());


从沙盒中读取数据

    // 读取    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];    // 根据key去取值    NSString *name = [defaults objectForKey:@"name"];    NSLog(@"%@",name);        NSInteger integer = [defaults integerForKey:@"age"];    NSLog(@"%ld",integer);


归档:

归档一般都是保存自定义对象的时候,使用归档.因为plist文件不能保存自定义对象.

如果一个字典当中保存有自定义对象,如果把这个字典写入到文件中,不会生产plist文件.


写入到沙盒的tmp目录下

archiveRootObject会调用encodeWithCode:方法

Person *person = [[Person alloc] init];    person.name = @"ZY";    person.age = 19;        Dog *dog = [[Dog alloc] init];    dog.name = @"wangcai";        person.dog = dog;        // 获取沙盒中的指定目录(tmp目录)    NSString *path = NSTemporaryDirectory();    NSLog(@"%@",path);    // 拼接文件名称    NSString *filePath = [path stringByAppendingPathComponent:@"person.data"];        // 归档(会调用encodeWithCoder方法) 把对象保存到沙盒的指定目录中    [NSKeyedArchiver archiveRootObject:person toFile:filePath];


unarchiveObjectWithFile会调用 initWithCoder方法

    // 接档操作    NSString *path = NSTemporaryDirectory();    NSString *filePath = [path stringByAppendingPathComponent:@"person.data"];        // 解档(什么类型,会调用initWithCoder: 方法)   Person *per =  [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];   NSLog(@"%@--%@",per.name,per.dog.name);

Person文件

#import <Foundation/Foundation.h>@class Dog;@interface Person : NSObject<NSCoding>/** 姓名 */@property(nonatomic,strong)NSString * name;/** 年龄 */@property(nonatomic,assign)int age;/** 狗 */@property(nonatomic,strong)Dog * dog;@end@implementation Person// 保存当前对象的哪些属性//- (void)encodeWithCoder:(NSCoder *)aCoder//{//    [aCoder encodeObject:self.name forKey:@"name"];//    [aCoder encodeInt:self.age forKey:@"age"];//}////// 当解析一个文件的时候调用.(告诉当前要解析文件当中哪些属性)//- (instancetype)initWithCoder:(NSCoder *)aDecoder//{//    if (self = [super init]) {//        self.name = [aDecoder decodeObjectForKey:@"name"];//        self.age = [aDecoder decodeIntForKey:@"age"];//    }//    //    return self;//}// 保存当前对象的哪些属性到沙盒中- (void)encodeWithCoder:(NSCoder *)aCoder{        [aCoder encodeObject:self.name forKey:@"name"];    [aCoder encodeInt:self.age forKey:@"age"];    [aCoder encodeObject:self.dog forKey:@"dog"];}// 当解析一个文件的时候调用(告诉当前要解析文件当中的哪些属性)- (instancetype)initWithCoder:(NSCoder *)aDecoder{    // 如果父类也准守了<NSCoding>协议,就可以调用initWithCoder:方法    if (self = [super init]) {        // 需要解析文件中哪些属性        self.name = [aDecoder decodeObjectForKey:@"name"];        self.age = [aDecoder decodeIntForKey:@"age"];        self.dog = [aDecoder decodeObjectForKey:@"dog"];    }    return self;}@end

NSKeyedArchiver-归档对象的注意

  • 如果父类也遵守了NSCoding协议,请注意:
  • 应该在encodeWithCoder:方法中加上一句

[super encodeWithCode:encode];

确保继承的实例变量也能被编码,即也能被归档

  • 应该在initWithCoder:方法中加上一句

self = [super initWithCoder:decoder];

确保继承的实例变量也能被解码,即也能被恢复




原创粉丝点击