iOS数据持久化方案
2016-07-09 本文已影响69人
来金德瑞
1.iOS中数据存储方式
- plist(NSArray/NSDictionary)
- preference(NSUserDefaults)
- NSCoding(NSKeyedArchiver/NSkeyedUnarchiver)
- SQlite3
- Core Data
优缺点分析
- plist(属性列表)是一种XML格式的文件,如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,就可以使用
writeToFile:atomically:encoding:error:
方法直接将对象写入属性列表文件中。但是对于自定义类无法使用,而且只能存储非常简单的数据。 - preference(偏好设置)一般用来保存用户的账号、密码、字体大小等,也同样只能存储一些简单数据类型,无法存储自定义对象
- 基于以上缺点,出现了NSCoding技术,NSCoding可以存储任何对象。只有遵守了
NSCoding
协议的对象,可以实现encodeWithCoder
归档对象,initWithCoder
恢复对象。 - 以上三种存在致命缺陷,无法存储大量数据,也无法实现非常便捷的CRUD(增删改查)。每次操作都要从文件中读取数据到内存中,然后增删改查,再写入文件,以旧文件覆盖新文件。大量IO操作,非常耗费性能。
- SQLite是纯C语言嵌入式关系型数据库,内存开销小、效率高,广泛使用于移动客户端。
- Core Data基于SQList,是苹果推出的基于OC版本的数据库技术,比较庞大,比较重量级,包装了很多层,所以效率不及SQLite3。
2.SQLite基本操作
1.准备工作
背景:在storyboard上添加两个textField和label,用来输入商品数据的名称和价格,点击添加按钮后,将其插入数据库。
- 导入框架libsqlite3.0.tbd
- 包含主头文件#import<sqlite3.h>
- 使用sqlite前先要打开数据库
//创建数据库文件名shop.sqlite
NSString *fileName = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:@"shop.sqlite"];
//打开数据库
int status = sqlite3_open(fileName.UTF8String, &_dataBase);
if (status == SQLITE_OK) {//打开成功
NSLog(@"打开数据库成功");
//SQL创表语句,id字段:主键,name:名称,price:价格
const char *sql = "CREATE TABLE IF NOT EXISTS t_shop (id integer PRIMARY KEY,name text NOT NULL,price real);";
char *error = NULL;
//执行sql语句
sqlite3_exec(self.dataBase, sql, NULL, NULL, &error);
if (error) {
NSLog(@"创表失败:%s",error);
}
}else{
NSLog(@"打开数据库失败");
}
代码解析:sqlite3_open()将根据文件路径打开数据库,如果数据库文件不存在,系统会自动创建文件自动初始化数据库。如果返回值status等于常量SQLITE_OK,表示数据库打开成功。第二个参数_dataBase
是该控制器sqlite3类型的属性,是一个打开的数据库实例。数据库文件的路径必须以C字符串(而非NSString)传入。一般服务器开发中打开数据库,都需要使用sqlite3_close(_dataBase
)关闭数据库,但在移动开发中,可以不用。
2.插入数据
//sql语句
NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_shop(name,price) VALUES('%@',%f);",self.nameField.text,self.priceField.text.doubleValue];
//执行sql,nameField和priceField是两个textField输入控件
sqlite3_exec(self.dataBase, sql.UTF8String, NULL, NULL, NULL);
代码分析:sqlite3_exec()可以执行任何sql语句,比如创表、更新、插入、删除操作等等。但一般不用它执行查询语句,因为它不会返回查询到的数据
3.查询数据
const char *sql = "SELECT name,price FROM t_shop";
//stmt指针是用来去除查询结果
sqlite3_stmt *stmt = NULL;
//准备
int status = sqlite3_prepare_v2(self.dataBase, sql, -1, &stmt, NULL);
if (status == SQLITE_OK) {//SQL语句正确,准备成功
while (sqlite3_step(stmt)==SQLITE_ROW) {//成功取出一条数据
const char *name = (const char *)sqlite3_column_text(stmt, 0);//取第一个字段
const char *price = (const char *)sqlite3_column_text(stmt, 1);//q取第二个字段
NSLog(@"%s,%s",name,price);
}
}
sqlite3_finalize(stmt);//销毁sqlite3_stmt对象
代码解析:sqlite3_step()返回SQLITE_ROW代表遍历到一条新纪录,sqlite3_column_*()用于获取每个字段对应的值,第2个参数是字段的索引,从0开始。
4.模糊查找
//searchText是需要查询的关键字
NSString *sql = [NSString stringWithFormat:@"SELECT name,price FROM t_shop WHERE name LIKE '%%%@%%' OR price LIKE '%%%@%%' ;", searchText, searchText];
sqlite3_stmt *stmt = NULL;
int status = sqlite3_prepare_v2(self.db, sql.UTF8String, -1, &stmt, NULL);
if (status == SQLITE_OK) {
while (sqlite3_step(stmt) == SQLITE_ROW) {
const char *name = (const char *)sqlite3_column_text(stmt, 0);
const char *price = (const char *)sqlite3_column_text(stmt, 1);
NSLog(@"%s,%s",name,price);
}
}
sqlite3_finalize(stmt);
代码分析:模糊查找与一般查找除了sql语句不同,其他都是一样的。唯一需要注意的是,在数据库中%表示任意东西,%S%表示字符S右边和左边可以是任何东西,在OC中%表示特殊意义,所以要写两个(%%)表示一个(%)。
5.sqlite函数总结
1.打开数据库
int sqlite3_open(
const char *filename, // 数据库的文件路径
sqlite3 **ppDb // 数据库实例
);
2.执行任何SQL语句
int sqlite3_exec(
sqlite3 *, // 一个打开的数据库实例
const char *sql, // 需要执行的SQL语句
int (*callback)(void*,int,char**,char**), // SQL语句执行完毕后的回调
void *, // 回调函数的第1个参数
char **errmsg // 错误信息
);
3.检查SQL语句的合法性(查询前的准备)
int sqlite3_prepare_v2(
sqlite3 *db, // 数据库实例
const char *zSql, // 需要检查的SQL语句
int nByte, // SQL语句的最大字节长度
sqlite3_stmt **ppStmt, // sqlite3_stmt实例,用来获得数据库数据
const char **pzTail
);
4.查询一行数据
int sqlite3_step(sqlite3_stmt*); // 如果查询到一行数据,就会返回SQLITE_ROW
5.利用stmt获得某一字段的值(字段的下标从0开始)
double sqlite3_column_double(sqlite3_stmt*, int iCol); // 浮点数据
int sqlite3_column_int(sqlite3_stmt*, int iCol); // 整型数据
sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); // 长整型数据
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); // 二进制文本数据
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); // 字符串数据
最后
第一篇博客,有很多问题,还没写全,如果想到了再做补充吧。使用这些sqlite原生的C语言API非常费力,以后有空介绍一下iOS中最常使用的数据库框架FMDB吧
That's All