iOS数据持久化

iOS有一套完整的数据安全体系,iOS应用程序只能访问自己的目录,这个目录成为沙箱目录,应用程序之间禁止数据的共享和访问。访问一些特殊的应用,如:联系人应用,必须通过特定的API访问。


一、沙箱目录


沙箱目录是一种数据安全策略,很多系统都采用沙箱设计(如,Android系统)。沙箱目录设计原理是只能允许自己的应用访问目录,而不允许其他的应用访问。


应用沙箱目录下有Documents、Library、tmp三个子目录。


1、Documents


该目录用于存储非常大的文件或需要非常频繁更新的数据,能够进行iTunes或Cloud的备份。我们可以通过下面的代码获取Documents的路径:


NSArray *documents= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath=[documents objectAtIndex:0];

documents是只有一个元素的数组,所以我们取第一个。

我的iPhone应用在iPad2上获取到的Documents路径是:


/var/mobile/Applications/9BBA2646-E70E-4ACF-A3DB-41C44833A01A/Documents


路径中的“9BBA2646-E70E-4ACF-A3DB-41C44833A01A”是应用程序ID,在安装时由系统分配。


2、Library


在Library目录下有PreferencePanes和Caches目录,其中前者用于存放应用程序的设置数据,后者与Documents相似,可以存放应用程序的数据,用来缓存文件。


同样,我们可以通过下面的代码获取到Library的路径:


NSArray *dirs= NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *path=[dirs objectAtIndex:0];

我的iPhone应用在iPad2上获取到的Library路径是:


/var/mobile/Applications/9BBA2646-E70E-4ACF-A3DB-41C44833A01A/Library



要获取Library下的Cahces目录只需要修改上面NSSearchPathForDirectoriesInDomains的第一个参数:


NSArray *dirs= NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path=[dirs objectAtIndex:0];


我的iPhone应用在iPad2上获取到的Caches路径是:


/var/mobile/Applications/9BBA2646-E70E-4ACF-A3DB-41C44833A01A/Library/Caches



PreferencePanes路径也能用上述方法获取到,这里不再赘述。


3、tmp


tmp是临时文件目录,用户可以访问。它不能进行iTunes或iCloud的备份。我们可以通过下面的方式获取到tmp的路径:


我的iPhone应用在iPad2上获取到的Caches路径是:


/private/var/mobile/Applications/9BBA2646-E70E-4ACF-A3DB-41C44833A01A/tmp/


二、数据持久化


数据持久化方式就是数据存储的方式,iOS支持本地存储和云端存储。本地存储主要有以下几种方式:


属性列表:集合对象可以读写到属性列表文件中。


对象归档:对象状态可以保存到归档文件中。


SQLite:开源嵌入式关系型数据库。


Core Data:一种对象关系映射技术(ORM),本质上也是通过SQLite存储的。



属性列表文件和对象归档一般用于存储少量数据。属性列表文件的访问要比对象归档的访问简单,Foundation框架集合对象都有对应的方法读写属性列表文件,对象归档是用NSData实现的。SQLite数据库和Core Data一般用于有几个简单表关系的大量数据的存储。



1、属性列表


属性列表文件是一种XML文件,Foundation框架中的数组和字典等都可以与属性列表文件互相转换。


属性列表文件使用比较简单,也很常用,这里不再赘述。



2、对象归档


对象归档是一种序列化。为了便于数据的传输,先将归档对象序列化成文件,然后再通过反归档将数据恢复到对象中。归档技术可以实现数据的持久化,这种方式不适合大量数据和频繁读写的情况。


对一个对象进行完整归档必须满足一定的条件:对象类必须实现NSCoding协议,而且每个成员变量应该是基本数据类型或都是实现了NSCoding协议的某个类实例


NSData提供了一些读写文件的方法,因此归档和反归档总是与NSData关联在一起使用。


归档过程是使用NSKeyedArchiver对象归档数据,具体过程为:先将归档数据写入NSData对象,然后在将NSData对象写入归档文件中。


反归档过程是从归档文件中读取数据到NSData对象,再利用NSKeyedUnarchiver对象从NSData对象中反归档出数据。


下面是示例代码片段:


(1)对象归档

    NSString *path = [self applicationDocumentsDirectoryFile];
        
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
        
    NSDate *date1 = [dateFormatter dateFromString:@"2010-08-04 16:01:03"];
    Note* note1 = [[Note alloc] init];
    note1.date = date1;
    note1.content = @"Welcome to MyNote.";
        
    NSDate *date2 = [dateFormatter dateFromString:@"2011-12-04 16:01:03"];
    Note* note2 = [[Note alloc] init];
    note2.date = date2;
    note2.content = @"欢迎使用MyNote。";
        
    NSMutableArray* array  = [[NSMutableArray alloc] init];

        
    [array addObject:note1];
    [array addObject:note2];
        
    NSMutableData * theData = [NSMutableData data];
    NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc]
                                      initForWritingWithMutableData:theData];
    [archiver encodeObject:array forKey:ARCHIVE_KEY];
    [archiver finishEncoding];
        
    [theData writeToFile:path atomically:YES];

- (NSString *)applicationDocumentsDirectoryFile {
    NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    NSString *path = [documentDirectory stringByAppendingPathComponent:FILE_NAME];
	return path;
}

Note实现了NSCoding协议:

#import <Foundation/Foundation.h>

@interface Note : NSObject < NSCoding>

@property(nonatomic, strong) NSDate* date;
@property(nonatomic, strong) NSString* content;

@end

#import "Note.h"

@implementation Note


-(void)encodeWithCoder:(NSCoder *)aCoder {
	[aCoder encodeObject:_date forKey:@"date"];
	[aCoder encodeObject:_content forKey:@"content"];
}

-(id)initWithCoder:(NSCoder *)aDecoder {
	self.date = [aDecoder decodeObjectForKey:@"date"];
	self.content = [aDecoder decodeObjectForKey:@"content"];
	return self;
}


@end


(2)对象反归档

    NSString *path = [self applicationDocumentsDirectoryFile];
    
    NSMutableArray *listData = [[NSMutableArray alloc] init];
    NSData * theData =[NSData dataWithContentsOfFile:path];
    
    if([theData length] > 0) {
		NSKeyedUnarchiver * archiver = [[NSKeyedUnarchiver alloc]
                                        initForReadingWithData:theData];
		listData = [archiver decodeObjectForKey:ARCHIVE_KEY];
		[archiver finishDecoding];

	}


3、SQLite是嵌入式系统中使用的关系数据库,目前主流版本是SQLite 3。SQLite运行时与使用它的应用程序之间共用相同的进程空间,而不是单独的两个进程。


SQLite提供了对SQL-92标准的支持,支持多表、索引、事物、视图和触发。SQLite是无数据类型的数据库,就是字段不用指定类型。


虽然SQLite可以忽略数据类型,但从编码规范上讲,应该在建表语句中指定数据类型,这样便于代码的阅读和理解。SQLite支持的常见数据类型如下:

INTEGER,有符号的整数类型。

REAL,浮点类型。

TEXT,字符串类型,采用UTF-8和UTF-16字符编码。

BLOB,二进制大对象类型,能够存放任何二进制数据。

SQLite提供的API比较多,文档对SQLite的用法以及一些API描述得很详细,实际使用过程中我们可以查阅文档。比如,在创建数据库时,我们需要经过如下3个步骤:

(1)使用sqlite3_open打开数据库;

(2)使用sqlite3_exec执行Create Table语句,创建数据表;

(3)使用sqlite3_close释放资源。


这些都是SQLite提供的C语言API,在OC中使用时需要注意数据类型的兼容问题。


其他像查询、删除等过程的调用,文档上都有详细的说明,这里就不赘述了。


这里还有一点需要注意,在使用SQLite之前,我们需要在工程中添加SQLite 3的库libsql3.dylib或libsql3.0.dylib。



4、Core Data


Core Data是一种ORM(对象关系映射。ORM是关系模型数据和对象模型类之间的一个纽带)技术。Core Data是Apple为Mac OS X和iOS系统应用开发提供的数据持久化技术。它基于高级数据持久化API,它的底层最终是SQLite、二进制文件和内存数据保存,这样应用开发层面不用关心数据的存储细节,不用再使用SQL语句,也不用面对SQLite的C语言函数。


关于Core Data的使用,见下一篇博客“Core Data”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值