美文网首页
iOS数据持久化方案

iOS数据持久化方案

作者: 来金德瑞 | 来源:发表于2016-07-09 13:59 被阅读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,用来输入商品数据的名称和价格,点击添加按钮后,将其插入数据库。

    1. 导入框架libsqlite3.0.tbd
    2. 包含主头文件#import<sqlite3.h>
    3. 使用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

    相关文章

      网友评论

          本文标题:iOS数据持久化方案

          本文链接:https://www.haomeiwen.com/subject/exgrjttx.html