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”。
1194

被折叠的 条评论
为什么被折叠?



