@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);

@import url(/css/cuteeditor.css);

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);

@import url(/css/cuteeditor.css);

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);

@import url(/css/cuteeditor.css);

@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);

@import url(/css/cuteeditor.css);

@import url(/css/cuteeditor.css);

1. 功能

第三个持久化选项是IOS的嵌入式SQL数据库,名为SQLite3,但其并非是Apple所提供的,而是第三方的数据库,可以应用于IOS、android、Linux和windows等系统。SQLite3提供多种方式的接口,有命令行的接口、客户端及多种语言的API接口。

本文只针对IOS系统下的C语言编程接口进行讨论,所以先介绍C语言的编程方式。

1.1 第一个程序:封装查询

如下是使用 sqlite3 C API的源文件,该程序主要功能是创建一个数据库文件,接着创建一个表,然后插入一条数据,最后查询表输出表内容。

  1.  1 int main()
  2.  2 {
  3.  3         sqlite3 *db;
  4.  4         char *zErrMsg = 0;
  5.  5         int rc;
  6.  6         char *baseName ="base";
  7.  7         char *createSQL = "create table episodes(id integer primary key, season int, name text);";
  8.  8         char *insertSQL = "insert into episodes(id,name) values(1,\"hello\");";
  9.  9         char *selectSQL = "select * from episodes;";
  10. 10 
  11. 11         rc = sqlite3_open(baseName, &db);     //创建数据库
  12. 12         rc = sqlite3_exec(db, createSQL, NULL, NULL, &zErrMsg);    //创建表
  13. 13         rc = sqlite3_exec(db, insertSQL, NULL, NULL, &zErrMsg);    //插入数据
  14. 14 
  15. 15         char **result;
  16. 16         int nrow,  ncolumn;
  17. 17 
  18. 18         rc = sqlite3_get_table(db, selectSQL,&result,&nrow,&ncolumn,&zErrMsg);     //查询表格
  19. 19         int i, j;
  20. 20         for(i=0; i<=nrow; i++)
  21. 21         {
  22. 22                 for(j=0; j<ncolumn; j++)
  23. 23                     printf("%s\t",result[i*ncolumn+j]);
  24. 24                 printf("\n");
  25. 25         }
  26. 26 
  27. 27        sqlite3_close(db);
  28. 28        return 0
  29. 29 }

编译命令:

在Linux平台上,要编译sqlite3源文件,需要将sqlite3.c文件拷贝到源程序文件所在的目录,然后按如下进行编译。

  1. gcc sqlite3.c firstSqlite.-lpthread ldl 

1.2 第二个程序:准备查询

准备查询由三个步骤组成:准备、执行和完成

  • 查询例程

    1.  1 void test_prepare_select()
    2.  2 {
    3.  3         int rc, i,ncols;
    4.  4         sqlite3 *db;
    5.  5         sqlite3_stmt *stmt;
    6.  6         char *sql="select * from episodes;";;
    7.  7         const char *tail;
    8.  8 
    9.  9         rc = sqlite3_open("base",&db);   //fprintf(stderr, "can't  open datebase:%s\n",sqlite3_errmsg(db));
    10. 10         rc = sqlite3_prepare_v2(db,sql,-1,&stmt,&tail);  //准备
    11. 11         rc = sqlite3_step(stmt);      //执行
    12. 12         while(rc != SQLITE_DONE)
    13. 13         {
    14. 14                 ncols = sqlite3_column_count(stmt);
    15. 15                 for(i=0; i<ncols; i++)
    16. 16                 {
    17. 17                         printf("'%s'",sqlite3_column_text(stmt,i));
    18. 18                 }
    19. 19                 printf("\n");
    20. 20                 rc = sqlite3_step(stmt);
    21. 21         }
    22. 22 
    23. 23         sqlite3_finalize(stmt);     //完成
    24. 24         sqlite3_close(db);
    25. 25 }
  • 绑定  
  1.  1 void test_prepare_bind()
  2.  2 {
  3.  3         int rc, i,ncols;
  4.  4         sqlite3 *db;
  5.  5         sqlite3_stmt *stmt;
  6.  6         char *sql = "insert into episodes (id,name) values (?, ?);";
  7.  7         const char *tail;
  8.  8         char *createSQL = "create table episodes(id integer primary key, season int, name text);";
  9.  9         char *zErrMsg = 0;
  10. 10 
  11. 11         sqlite3_open("base",&db);
  12. 12         sqlite3_exec(db, createSQL, NULL, NULL, &zErrMsg);
  13. 13 
  14. 14         sqlite3_prepare_v2(db,sql,-1,&stmt,&tail);
  15. 15         sqlite3_bind_int(stmt, 1, 1);
  16. 16         sqlite3_bind_text(stmt,2,"hello", strlen("hello"), SQLITE_TRANSIENT);
  17. 17         sqlite3_step(stmt);
  18. 18     
  19. 19         sqlite3_finalize(stmt);
  20. 20         sqlite3_close(db);
  21. 21 }

2.  SQLite3设计与概念

2.1 API对象模型

SQLite3 C API 的对象模型结构可以由下图表示,即任何一个SQlite3数据库都存储在操作系统文件中——一个数据库对应一个操作系统文件。

图 2

2.1.1 连接与语句

API中与查询处理有关的两个基本数据结构是连接(sqlite3)和语句(sqlite3_stmt),API中所有的主要操作都在使用这两个结构。其中连接负责管理语句,由于在一个时刻,一个连接中只能存在一个语句,所以在每个连接中都设置一个table Locks的锁,从而保证这种唯一性。

      1)连接:sqlite3

             一个连接对象代表到数据库的连接和事务上下文,statement来自连接对象;

      2)语句:sqlite3_Stmt

           一个statement对象代表了一个编译的SQL语句。在内部,它使用VDBE字节码来表示,VDBE字节码是一个会执行SQL命令的程序。statement包括执行一个命令所需要的一切东西。

2.1.2 B-tree与Pager

一个连接对象可以连接到多个数据库对象——一个主数据库和多个附加数据库。每个数据库对象都有一个B-tree和相应的一个pager对象。statement使用它们连接对象的B-tree和pager从数据库中读取数据,向数据库写入数据。并且保证一个数据库只存在一个连接,从而产生一个Database Lock的锁。

     1)B-tree

B-tree负责与语句进行交互,即读取数据库的statement使用游标遍历B-tree。然后b-tree从pager中读取数据。

     2)pager

若一个游标想要访问页面,则pager必须从内存加载到磁盘中,然后返回给b-tree。并且当游标修改页面时,pager必须采取特殊措施保留原始页面,确保在发生事务回滚时可以回到原来的状态。即pager负责读写数据库,维护内存缓存或者页面,管理事务。

2.2 核心API

核心API是用来执行SQL命令的,它由各种用来执行查询的函数和管理数据库的实用函数组成。执行SQL命令有两种方法:准备查询封装查询。在API和SQLite内部,准备查询方法最终执行所有命令的方法,它包含准备执行完成三个阶段,每个阶段都有一个单独的API函数而封装查询方法是将准备查询的三个步骤封装成为一个函数调用,并提供了一次执行SQL命令的简便方法。即

  • 准备查询

         1)准备:sqlite3_prepare();

         2)执行:sqlite3_step();

         3)完成:sqlite3_finalize();

  • 封装查询

    1)sqlite3_exec()

  • 2)sqlite3_get_table()

2.2.1 连接数据库

因为SQLite数据库其实就是一个操作系统文件,所以连接数据库其实就是打开系统文件。C API 中用于连接或打开一个数据库的函数sqlite3_open(),基本上就是一个打开文件的系统调用。若打开的数据库文件不存在,则创建一个新的数据库;若存在则将SQLite文件打开。一旦开打一个数据库文件,那么将使用一个不透明的sqlite3连接句柄来表示它,该句柄表示到数据库的一个连接。sqlite扩展中,连接对象抽象了该句柄,并且有时一些对应的API函数实现方法将该句柄作为参数。

2.2.2 执行准备查询

正如上述所述,准备查询方法中执行一条SQL命令,需要由三个步骤组成:

       1)准备

            在C API中,这个步骤由sqlite3_prepare_ve()函数完成,该函数直接与编译器对话。编译器将命令编译成为VDBE字节码,即创建sqlit3_stmt句柄。

       2)执行

           执行是一个逐步的过程,CAPI中每一步都由sqlite3_step()发起,并使VDBE逐步执行字节码,第一次调用sqlite3_step()通常需要某种类型的锁,锁的类型根据    执行什么样的命令(读或写)而变化。对于select语句,sqlite3_step()的每次调用将使语句句柄的游标位置移动到结果集的下一行。对于结果集中的每一行,游标未到达结果集末尾时,将返回SQLITE_ROW;否则,将返回SQLITE_DONE。对于其他SQL语句(insert、update、delete等),第一次调用sqlite3_step()将促使VDBE执行整个命令。

      3)完成

VDBE关闭语句并释放资源。C API中,由sqlite_finalize()来执行,该函数使得VDBE终止程序、释放资源并关闭statement句柄。

每一步(准备、执行、完成)对应statement句柄的各自状态(准备状态、执行状态、完成状态)。准备状态以为这所有必需的资源以及分配,statement已准备执行,但是没有启动,没有获得锁,也没有申请获得锁,直到第一次调用sqlite3_step()时才开始获取锁。活动状态从第一次调用sqlite3_step()开始。此时,statement处于执行过程中,并且开始使用某种类型的锁。完成状态意味着开始使用关闭,并且所有相关的资源已被释放。如下图所示:

图 3

2.2.3 使用参数化SQL

SQLite3语句可以包含参数,即该参数就是占位符,可能会在编译后为其提供(或"绑定")值。当sqlite3_prepare_v2()编译带有参数的语句时,它在结果语句句柄中为这些参数分配占位符。然后,期望语句执行前为这些参数提供值,如果参数没有绑定值,执行该语句时SQLite默认使用NULL。

其中提供了两种方式的绑定:位置绑定和命名绑定;

  1. insert into episodes(id, name) values (?, ?); 
  2. insert into episodes(id, name) values(:id,:name)

      1)位置绑定

位置绑定是通过问号定义的,第一个问号表示位置1,第二个为2,依次类推。

      2)命名绑定

命名绑定使用实际变量名,以冒号作为前缀。

参数绑定的优点是无需重新编译,就可以多次执行相同的语句。只需重置该语句、绑定新值、并重新执行。这时重置函数(sqlite3_reset)就可以发挥作用了:它可以避免SQL编译的开销;并且参数绑定能够使SQlite会处理绑定参数的转义字符。

3. 核心C API

SQLite v3 API包括许多函数。不过,只有8个函数是实际处理连接、处理查询,并断开与数据库连接所必需的。其余函数可以归入专门用于完成特定任务的小组中。可以查询C API参考手册(网址是www.sqlite.org/c3ref/intro.html)。

3.1 连接与断开连接: sqlite3_open_v2、sqlite3_close

在执行SQL命令前,首先要连接数据库。也许将连接数据库称为打开数据库才是更好的表述,因为SQLite数据库包含在单个操作系统文件(一个文件对应一个数据库)中。同理,断开连接可以成为关闭数据库。

      1)打开数据库

  1. int sqlite3_open_v2(
  2.     const char *filename,    //数据库文件名
  3.     sqlite3 **ppDb,        //OUT:SQLite数据库句柄
  4.     int flags,                //标志
  5.     const char *zVfs        //要使用的VFS模块的名称
  6. );

参数filename是操作系统文件,或文本字符串':memory:',或空字符串,或空指针。如果使用':memory:',sqlite3_open_v2()将在内存中创建数据库,该数据库只存在于连接生成期间。如果文件名是空字符串或null,sqlite3_open_v2()将打开磁盘文件,并在连接关闭时自动删除该文件。

      2)关闭数据库

  1. int sqlite3_close(sqlite3*)

要成功执行sqlite3_clsose(),必须完成与连接关联的所有准备查询。只要有一个查询仍未完成,sqlite3_close()都会返回SQLITE_BUSY并显示错误消息"由于有未完成的语句,所以无法关闭连接"。

3.2 封装查询

3.2.1 执行查询:sqlite3_exec

        函数sqlite3_exec()提供一种快速、方便执行SQL命令的方法,对修改数据库的命令(即不返回任何数据的命令)特别方便。因此,通常也称为便捷函数,一个简单的API调用就能很好地封装很多其他任务。该函数的声明如下:

  1. int sqlite3_exec(
  2.     sqlite3*,             //打开的数据库
  3.     const char *sql,    //要执行的SQL
  4.     sqlite_callback,    //回调函数
  5.     void *dta,            //回调函数的第一个参数
  6.     char **errmsg        //错误信息
  7. );

其中SQlite提供的回调函数声明如下:

  1. typedef  int (*sqlite3_callback)(
  2.     void*,        //sqlite3_exe()函数第四个参数提供的数据
  3.     int,            //行中字段的数目
  4.     char**,        //代表行中字段名称的字符串数组
  5.     char**        //代表字段名称的字符串数组
  6. )

3.2.2 获取查询:sqlite3_get_table

      行数sqlite3_get_table()返回单独函数调用中一个命令的整个结果集,与sqlite3_exec()类似也是封装了准备查收API函数的一些函数,可以一下运行全部的命令。sqlite3_get_table()函数接收SQL语句并返回所有记录,使用堆上声明的内存(使用sqlite3_malloc())将他们存储在参数result中。必须使用sqlite3_free_table()释放内存,该函数将resultp指针作为唯一的参数。resultp中的一个记录实际上不是记录,而是结果集中列的名称。

  1. int sqlite3_get_table(
  2.     sqlite3*,                //打开的数据库
  3.     const char *sql,        //要执行的SQL
  4.     char ***resultp,        //结果写入该指针执行的char *[]
  5.     int *nrow,            //结果集中行的数目
  6.     int *ncolumn,            //结果集中字段的数目
  7.     char **errmsg            //错误信息
  8. )

3.4 准备查询

3.3.1 准备

编译或准备接收SQL语句,并将其编译为虚拟数据库引擎(VDBE)可读的字节码。这是由函数sqlite3_prepare_v2()完成的,其声明如下:

  1. int sqlite3_prepare_v2(
  2.     sqlite3 *db,            //数据库句柄
  3.     const char *zSql,        //SQL文本
  4.     int nBytes,
  5.     ssqlite3_stmt **ppStmt,
  6.     const char **pzTail
  7. )

3.3.2 执行

一旦查询语句准备就绪,下一步就是使用sqlite3_step()执行,sqlite3_step()声明如下:

  1. int sqlite3_step(sqlite3_stmt *pStmt);

对于不返回数据的SQL语句,对sqlite3_step()的第一次调用就执行完SQL语句,并返回一个指示结果的代码。对于返回数据的SQL语句,例如select语句,sqlite3_step()第一次调用将语句定位在第一个记录的B-tree光标上。后续调用的sqlite3_step()将光标定位在结果集内的后续记录。到底末尾值之前,sqlite3_step()为结果集中的每个记录返回SQLITE_ROW。返回SQLITE_DONE,表示游标已到底结果集末尾。

3.3.3 完成与重置

一旦语句执行结束,必须终止。可以使用如下之一完成或重置语句:

  1. int slqite3_finalize(sqlite3_stmt *pStmt);
  2. int sqlite3_reset(sqlite3_stmt *pStmt);
  3. sqlite3_finalize()将关闭语句。释放资源并提交或回滚任何隐式事务。

如果要重复使用语句,可以使用sqlite3_reset()。该函数将保持已编译的SQL语句(和任何绑定的参数),但是会将单签语句相关联的变化提交到数据库。执行sqlite3_finalize()后将释放资源并提交或回滚任何隐藏事物,清除日志文件并释放相关的锁。sqlite3_finalize()和sqlite3_reset()之间的主要差别在于后者保留与语句关联的资源,使它可以重新执行,避免了再次调用sqlite3_prepare()编译SQL命令。

3.4 获取记录

对于返回记录的语句而言,可以使用函数sqlite3_column_count()和sqlite3_dta_count()获得结果集中的字段数,这两个函数声明如下:

  1. int sqlite3_column_count(sqlite3_stmt *pStmt);
  2. int sqlite3_data_count(sqlite3_stmt *pStmt);

3.4.1 获取字段信息

可以是会用sqlite3_column_name()函数获取当前记录中的所有列。同样,可以使用sqlite3_column_type()函数获取每个字段关联的存储类。

3.4.2 获取字段值

可以使用sqlite3_column_xxx()函数获取当前记录中的所有字段值,该函数的通用形式如下:

  1. xxx sqlite3_column_xxx(
  2.     sqltie3_stmt *,    //语句句柄
  3.     int iCol            //字段的次序
  4. )

3.5 查询参数化

       准备语句后,可以使用sqlite3_bind_xxx()函数绑定参数值。这些函数的一般形式如下:

  1. sqlite3_bind_xxx(
  2.     sqlite3_stmt*,        //语句句柄
  3.     int I,                //参数个数
  4.     xxx value            //绑定的值
  5. )

4. IOS使用

4.1 配置

由于SQLite3是第三方的数据库,若想在Xcode中使用需要做一些配置。

4.1.1 链接到SQLite3库

在项目中的Build Phases选项中的Link Binary With Libraries下,点击其"+"号,从而添加所需要的libsqlite3.tbd或者是libsqlite3.dylib库。如图 4所示。

图 4

4.1.2 添加SQLite3头文件

由于SQLite3没有提供swift和Object-C的API接口,所以只能使用其提供的C语言接口。那么在Swift环境中使用SQLite3需要添加桥接头文件;而在Object-C环境中则可以使用C语言接口。如图 5所示。

图 5

4.2 API 调用

SQLite3的API有两种使用方式:封装查询和准备查询。准备查询是由三个步骤组成:准备、执行和完成;而封装查询是对准备查询的三个步骤进行封装,从而只需一步就能完成三个步骤。由于在Object-C中可以直接使用SQLite3的API,所以本文就不对其进行详述,而讨论在swift环境中的SQLite3使用进行讨论。具体SQLite3的设计和概念可以参考另一片博文:SQLite3 API总结。

4.2.1 封装查询:swift 

  1.  1 func testSqlite3()
  2.  2 {
  3.  3         //1:获取Documents的路径,并创建file.txt的路径
  4.  4         let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true);
  5.  5         var documentsDirectory = paths[0] as String;
  6.  6         documentsDirectory = documentsDirectory.stringByAppendingString("/database");
  7.  7         
  8.  8         var db:COpaquePointer = nil;
  9.  9         var rc:Int32
  10. 10         var zErrMsg:UnsafeMutablePointer<Int8> = UnsafeMutablePointer<Int8>.alloc(1)
  11. 11 
  12. 12         let baseName = documentsDirectory;
  13. 13         let createSQL = "create table episodes(id integer primary key, season int, name text);";
  14. 14         let insertSQL = "insert into episodes(id,name) values(1,\"hello\");";
  15. 15         let selectSQL = "select * from episodes;";
  16. 16 
  17. 17         rc = sqlite3_open(baseName, &db);     //创建数据库
  18. 18         rc = sqlite3_exec(db, createSQL, nil, nil, &zErrMsg);    //创建表
  19. 19         rc = sqlite3_exec(db, insertSQL, nil, nil, &zErrMsg);    //插入数据
  20. 20         var result:UnsafeMutablePointer<UnsafeMutablePointer<Int8>> = UnsafeMutablePointer<UnsafeMutablePointer<Int8>>.alloc(322)
  21. 21         var nrow:Int32 = 0
  22. 22         var ncolumn:Int32 = 0
  23. 23         
  24. 24         rc = sqlite3_get_table(db, selectSQL,&result, &nrow, &ncolumn, &zErrMsg);     //查询表格
  25. 25     
  26. 26         var i:Int32
  27. 27         var j:Int32
  28. 28         for i=0; i <= nrow; i++
  29. 29         {
  30. 30             for j=0; j<ncolumn; j++
  31. 31             {
  32. 32             let ij:Int = Int(i*ncolumn+j)
  33. 33                 if nil != result[ij]
  34. 34                 {
  35. 35                     NSLog(String.fromCString(result[ij])!);
  36. 36                 }
  37. 37             }
  38. 38                 print("\n");
  39. 39         }
  40. 40         sqlite3_close(db);
  41. 41 }

4.2.2 准备查询:swift

  1.  1 func prepareSQLite3()
  2.  2 {
  3.  3         //1:获取Documents的路径,并创建file.txt的路径
  4.  4         let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true);
  5.  5         var documentsDirectory = paths[0] as String;
  6.  6         documentsDirectory = documentsDirectory.stringByAppendingString("/database");
  7.  7 
  8.  8         var db:COpaquePointer = nil;
  9.  9         var statement:COpaquePointer = nil
  10. 10         var rc:Int32
  11. 11         var zErrMsg:UnsafeMutablePointer<Int8> = UnsafeMutablePointer<Int8>.alloc(1)
  12. 12 
  13. 13         let baseName = documentsDirectory;
  14. 14         let createSQL = "create table episodes(id integer primary key, season integer, name text);";
  15. 15         let insertSQL = "insert into episodes(id,season,name) values(2,2,\"hello\");";
  16. 16         let selectSQL = "select * from episodes;";
  17. 17         
  18. 18         rc = sqlite3_open(baseName, &db);     //创建数据库
  19. 19         rc = sqlite3_exec(db, createSQL, nil, nil, &zErrMsg);    //创建表
  20. 20         rc = sqlite3_exec(db, insertSQL, nil, nil, &zErrMsg);    //插入数据
  21. 21 
  22. 22         //准备查询
  23. 23         sqlite3_prepare_v2(db, selectSQL, -1, &statement, nil)
  24. 24         rc = sqlite3_step(statement)
  25. 25         while rc != SQLITE_DONE
  26. 26         {
  27. 27             let ncols = sqlite3_column_count(statement);
  28. 28             for var i:Int32 = 0; i < ncols; i++
  29. 29             {
  30. 30                 if nil != sqlite3_column_text(statement, i)
  31. 31                 {
  32. 32                     NSLog(String.fromCString(UnsafePointer<CChar>(sqlite3_column_text(statement, i)))!)
  33. 33                 }
  34. 34             }
  35. 35             rc = sqlite3_step(statement)
  36. 36         }
  37. 37         
  38. 38         sqlite3_finalize(statement)
  39. 39         sqlite3_close(db)
  40. 40 }

iOS 数据持久化(2):SQLite3的更多相关文章

  1. iOS 数据持久化(扩展知识:模糊背景效果和密码保护功能)

    本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...

  2. iOS数据持久化方式及class_copyIvarList与class_copyPropertyList的区别

    iOS数据持久化方式:plist文件(属性列表)preference(偏好设置)NSKeyedArchiver(归档)SQLite3CoreData沙盒:iOS程序默认情况下只能访问自己的程序目录,这 ...

  3. iOS开发笔记-swift实现iOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (plist.NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data.第三方类库等 归档(又名 ...

  4. IOS数据持久化之归档NSKeyedArchiver

    IOS数据持久化的方式分为三种: 属性列表 (自定义的Property List .NSUserDefaults) 归档 (NSKeyedArchiver) 数据库 (SQLite.Core Data ...

  5. iOS -数据持久化方式-以真实项目讲解

    前面已经讲解了SQLite,FMDB以及CoreData的基本操作和代码讲解(CoreData也在不断学习中,上篇博客也会不断更新中).本篇我们将讲述在实际开发中,所使用的iOS数据持久化的方式以及怎 ...

  6. iOS数据持久化-OC

    沙盒详解 1.IOS沙盒机制 IOS应用程序只能在为该改程序创建的文件系统中读取文件,不可以去其它地方访问,此区域被成为沙盒,所以所有的非代码文件都要保存在此,例如图像,图标,声音,映像,属性列表,文 ...

  7. iOS数据持久化

    在iOS中,实现数据持久化一般分为4大种: 1.属性列表 2.对象归档 3.SQLite 4.Core Data 一.属性列表 NSUserDefaults类的使用和NSKeyedArchiver有很 ...

  8. 转载 -- iOS数据持久化存储

    作者:@翁呀伟呀 授权本站转载 概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方 ...

  9. iOS 数据持久化(1):属性列表与对象归档

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css); @import url(/ ...

  10. iOS: 数据持久化方案

    数据持久化方案(如果总结不到位,或者有误的地方,敬请斧正) 一.功能: 主要是将数据持久化到本地,减少对网络请求的次数,既节省了用户的流量,也增强了App的体验效果. 二.种类:  plist存储:使 ...

随机推荐

  1. VS 调试相关

    最近用VS2013 调试遇到的一点小问题,老年痴呆做一下记录. 1. IIS 用 w3wp.exe 调试: IIS 中的文件系统与工程的保持一致,否则断点不会命中: 发布文件系统后,重启站点对应的应用 ...

  2. Android计量单位px,in,mm,pt,dp,dip,sp和获取屏幕尺寸与密度

    ###########################################Android计量单位########################################### px ...

  3. Life Forms

    poj3294:http://poj.org/problem?id=3294 题意:就是求n个串的中一个最大的子串,这个子串在超过n/2的串中出现. 题解:这是一道好题.首先一种解法就是用后缀数组来搞 ...

  4. java rest版简单的webservice

    目前的webservice风格,rest应该是其中一种 还有种就是soap,rest是轻量级的,越来越流行.下面举一个简单例子说明下rest的用法. 1. 准备ws的jar和spring的jar,如何 ...

  5. Keil工程文件的建立、设置与目标文件的获得

    单片机开发中除必要的硬件外,同样离不开软件,我们写的汇编语言源程序要变为 CPU 可以执行的机器码有两种方法,一种是手工汇编,另一种是机器汇编,目前已极少使用手工 汇编的方法了.机器汇编是通过汇编软件 ...

  6. 窗体前端显示(ShowWindowAsync有许多优点)

    H:=FindWindow('Tfrm_MainForm','aa');  if H>0 then  begin    ShowWindowAsync(h,SW_MAX);    SetFore ...

  7. TinyMCE logo 可视化HTML编辑器 TinyMCE

    TinyMCE是一个轻量级的基于浏览器的所见即所得编辑器,支持目前流行的各种浏览器,由JavaScript写成.功能配置灵活简单(两行代码就可以 将编辑器嵌入网页中),支持AJAX.另一特点是加载速度 ...

  8. 凯撒密码 CH Round #57 - Story of the OI Class

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2357%20-%20Story%20of%20the%20OI%20Class/凯撒密码 题解:刚开始想map, ...

  9. BZOJ1609: [Usaco2008 Feb]Eating Together麻烦的聚餐

    1609: [Usaco2008 Feb]Eating Together麻烦的聚餐 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 938  Solved ...

  10. A configuration error occurred during startup. Please verify the preference field with the prompt: Cannot connect to vm

    1.报错图 解决方法: Window->Preferences->MyEclipse Enterprice Workbench->Servers->Tomcat->选择你 ...