一、沙盒机制
沙盒是什么
每个iOS应用都有属于自己的应用沙盒(沙盒就是文件系统目录),与其他文件系统隔离,每个应用都只能访问自己的沙盒。
沙盒的路径结构
- Document:适合存储重要的数据, iTunes同步应用时会同步该文件下的内容,(比如游戏中的存档)
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
- Library/Caches:适合存储体积大,不需要备份的非重要数据,iTunes不会同步该文件
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
- Library/Preferences: 通常保存应用的设置信息, iTunes同步该应用时会同步此文件夹中的内容
- tmp:保存应用的临时文件,用完就删除,系统可能在应用没在运行时删除该目录下的文件,iTunes不会同步该文件
NSString *path = NSTemporaryDirectory();
获取沙盒路径
通过NSSearchPathForDirectoriesInDomains
方法来获取沙盒路径
二、数据存储常用方式
偏好设置(NSUserDefaults)
- 偏好设置是专门保存应用的配置信息的,如用户名、密码等,一般不要在偏好设置中保存其他数据。
- NSUserDefaults保存的数据都是不可变的,取出来的数据也是不可变类型,通过键值对方式进行存取。
- 如果没有调用
synchronize
方法,系统会根据I/O情况不定时刻地保存到文件中。所以如果需要立即写入文件的就必须调用synchronize
方法。 - 偏好设置会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件。
实例如下:
//获得NSUserDefaults文件
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
//保存内容
[userDefaults setValue:@"sunsan" forKey:username];
[userDefaults setValue:@"abcd1234" forKey:userpassword];
//读取内容
NSString * name = [userDefaults valueForKey:username];
NSString * password = [userDefaults valueForKey:userpassword];
plist存储
plist文件是将某些特定的类,通过XML文件的方式保存在目录中。
可以被序列化的类型有以下几种:
NSArray;
NSMutableArray;
NSDictionary;
NSMutableDictionary;
NSData;
NSMutableData;
NSString;
NSMutableString;
NSNumber;
NSDate;
实例如下:
//设置文件名
NSString *fileName = [path stringByAppendingPathComponent:@"students.plist"];
//写入文件
[array writeToFile:fileName atomically:YES];
//读取
NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
归档解归档
通过使用NSKeyArchiver的archiveRootObject: toFile:
方法直接归档一个对象,使用NSKeyedUnarchiver的unarchiveObjectWithFile:
解档对象。
在归档自定义对象的时候,必须遵守NSCoding协议,并实现协议方法:
- 每次归档对象时,都会调用
encodeWithCoder:
,一般在这个方法里面指定如何归档对象中的每个实例变量; - 每次从文件中恢复对象时,都会调用
initWithCoder:
,一般在这个方法里面指定如何解码文件中的数据为对象的实例变量。
实例如下:
//设置文件名
NSString *fileName = [path stringByAppendingPathComponent:@"person.archiver"];
//进行归档
[NSKeyedArchiver archiveRootObject:per toFile:fileName];
//进行解归档
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:fileName];
以上的存储方法,都是覆盖存储。如果想要增加一条数据就必须把整个文件读出来,然后修改数据后再把整个内容覆盖写入文件,并不适合大量数据的存取。
SQLite
SQLite简介
SQLite是一个轻量级关系数据库,最初的设计目标是用于嵌入式系统,它占用资源非常少。在iOS中,只要导入libsqlite3.0.tbd依赖以及引入sqlite3.h头文件即可。
SQLite是无类型的数据库,可以保存任何类型的数据,对于SQLite来说对字段不指定类型是完全有效的
SQLite近似类似规则
- 如果类型字符串中包含“int”,那么该字段的亲缘关系是INTEGER
- 如果类型字符串中包含“char”,“clob”或“text”,那么该字段的亲缘类型是TEXT
- 如果类型字符串中包含“blob”,那么该字段的亲缘类型是NONE
- 如果类型字符串中包含“real”,“floa”或“doub”,那么该字段的亲缘类型是REAL
- 其余情况下,字段的亲缘类型为NUMERIC
SQLite字段的约束条件
- not null —— 非空
- unique —— 唯一
- primary key —— 主键
- foreign key —— 外键
- check —— 条件检查,确保一列中所有的值满足一定条件
- default —— 默认
- autoincrement —— 自增型变量,该字段数据如果为整形可以自动加1
SQLite语句
SQL语言共分为四大类:数据查询语言DQL,数据操纵语言DML,数据定义语言DDL,数据控制语言DCL。
- DML主要包含数据的增删改:
数据插入(insert):insert into 表名(字段1,字段2,……)values(字段1值,字段2值,……)
数据更新(update):update 表名 set 字段1=修改值1,字段2=修改值2,……where 条件
数据删除(delete):delete from 表名 where 条件 - DQL主要用于查询获得表中的数据,其中差用的关键字包含where,order by,group by和having
数据查询(select):select 查找字段 from 表名 where 条件 - DDL部分包含创建或者删除表格,定义索引,规定表之间的链接,以及施加表间的约束
建表命令:create table if not exists 表名(字段1 约束1 约束2……,字段2 约束1 约束2)
删表命令:drop table if exists 表名
FMDB
FMDB是一款轻量级的框架,以OC的方式对SQLite的C语言API进行封装,对多线程并发进行处理,所以线程安全。
FMDB常用类
FMDatabase:一个FMDatabase对象就代表一个单独的SQLite数据库,用来执行SQL语句
FMResultSet:使用FMDatabase执行查询后的结果集
FMDatabaseQueue:用于在多线程中执行多个查询或更新,它是线程安全的
FMDB操作
- 使用FMDataBase类建立数据库
//获取Documents路径
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject ;
//生成数据库路径
NSString *filePath = [path stringByAppendingPathComponent:@"person.sqlite"];
//获取数据库
database = [FMDatabase databaseWithPath:filePath];
if ([database open]) {
NSLog(@"数据库打开成功");
}else{
NSLog(@"打开数据库失败");
}
- 表的创建
BOOL result = [database executeUpdate:@"create table if not exists person (name text primary key not null, city text, age integer)"];
if (result) {
NSLog(@"创建表成功");
} else {
NSLog(@"创建表失败");
}
- 添加数据
BOOL result = [database executeUpdate:@"insert into person (name,city,age) values (?,?,?)",per.name,per.city,@(per.age)];
if (result) {
NSLog(@"添加数据成功");
} else {
NSLog(@"添加数据失败");
}
- 删除数据
BOOL result = [database executeUpdate:@"delete from person where name = ?",per.name];
if (result) {
NSLog(@"删除数据成功");
} else {
NSLog(@"删除数据失败");
}
- 修改数据
BOOL result = [database executeUpdate:@"update person set city = ?,age = ? where name = ?",per.city,@(per.age),per.name];
if (result) {
NSLog(@"修改数据成功");
} else {
NSLog(@"修改数据失败");
}
- 查询所有数据
FMResultSet *result = [database executeQuery:@"select * from person"];
while ([result next]) {
Person *per = [[Person alloc] init];
per.name = [result stringForColumn:@"name"];
per.city = [result stringForColumn:@"city"];
per.age = [result intForColumn:@"age"];
[array addObject:per];
}
- 关闭数据库
if ([database close]) {
NSLog(@"关闭数据库成功");
} else {
NSLog(@"关闭数据库失败");
}
参考:完整项目资料下载