在iOS开发中使用FMDB

来源:互联网 发布:金10数据官网 双十一 编辑:程序博客网 时间:2024/06/12 23:07

http://blog.devtang.com/blog/2012/04/22/use-fmdb/


SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库。iOS SDK很早就支持了SQLite,在使用时,只需要加入 libsqlite3.dylib 依赖以及引入 sqlite3.h 头文件即可。但是,原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,开源社区中就出现了一系列将SQLite API进行封装的库,而FMDB (https://github.com/ccgus/fmdb) 则是开源社区中的优秀者。

FMDB在使用上相当方便。以下是一个简单的例子:

<span class="line-number">1</span><span class="line-number">2</span><span class="line-number">3</span><span class="line-number">4</span><span class="line-number">5</span><span class="line-number">6</span><span class="line-number">7</span><span class="line-number">8</span><span class="line-number">9</span><span class="line-number">10</span><span class="line-number">11</span>
NSString* docsdir = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) lastObject];NSString* dbpath = [docsdir stringByAppendingPathComponent:@"user.sqlite"];FMDatabase* db = [FMDatabase databaseWithPath:dbpath];[db open];FMResultSet *rs = [db executeQuery:@"select * from people"];while ([rs next]) {    NSLog(@"%@ %@",        [rs stringForColumn:@"firstname"],        [rs stringForColumn:@"lastname"]);}[db close];

可以看到,使用FMDB后的数据库代码清晰明了,比原生的API优雅多了。另外,FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。

使用说明

该使用说明主要翻译自fmdb的github项目说明文档: https://github.com/ccgus/fmdb

引入相关文件

首先将FMDB从github上clone下来,然后将以下文件copy到你的工程中:

<span class="line-number">1</span><span class="line-number">2</span><span class="line-number">3</span><span class="line-number">4</span><span class="line-number">5</span><span class="line-number">6</span><span class="line-number">7</span><span class="line-number">8</span><span class="line-number">9</span><span class="line-number">10</span>
FMDatabase.hFMDatabase.mFMDatabaseAdditions.hFMDatabaseAdditions.mFMDatabasePool.hFMDatabasePool.mFMDatabaseQueue.hFMDatabaseQueue.mFMResultSet.hFMResultSet.m

建立数据库

建立数据库只需要如下一行即可,当该文件不存在时,fmdb会自己创建一个。如果你传入的参数是空串:@”” ,则fmdb会在临时文件目录下创建这个数据库,如果你传入的参数是 NULL,则它会建立一个在内存中的数据库。

<span class="line-number">1</span>
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];

打开数据库

使用如下语句,如果打开失败,可能是权限不足或者资源不足。通常打开完操作操作后,需要调用close方法来关闭数据库。

<span class="line-number">1</span><span class="line-number">2</span><span class="line-number">3</span><span class="line-number">4</span><span class="line-number">5</span><span class="line-number">6</span><span class="line-number">7</span><span class="line-number">8</span>
if (![db open]) {    // error     return;}// some operation// ...[db close];

执行更新操作

除了Select操作之外,其它的都是更新操作。更新操作使用如下方法,如果有错误,可以用error参数中获得。

<span class="line-number">1</span>
-[FMDatabase executeUpdate:error:withArgumentsInArray:orVAList:]

执行查询操作

查询操作示例如下。注意:即使操作结果只有一行,也需要先调用FMResultSet的next方法。

<span class="line-number">1</span><span class="line-number">2</span><span class="line-number">3</span><span class="line-number">4</span><span class="line-number">5</span><span class="line-number">6</span><span class="line-number">7</span><span class="line-number">8</span><span class="line-number">9</span>
FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];while ([s next]) {    //retrieve values for each record}FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM myTable"];if ([s next]) {    int totalCount = [s intForColumnIndex:0];}

FMDB提供如下多个方法来获取不同类型的数据:

<span class="line-number">1</span><span class="line-number">2</span><span class="line-number">3</span><span class="line-number">4</span><span class="line-number">5</span><span class="line-number">6</span><span class="line-number">7</span><span class="line-number">8</span><span class="line-number">9</span><span class="line-number">10</span><span class="line-number">11</span>
intForColumn:longForColumn:longLongIntForColumn:boolForColumn:doubleForColumn:stringForColumn:dateForColumn:dataForColumn:dataNoCopyForColumn:UTF8StringForColumnIndex:objectForColumn:

通常情况下,你并不需要关闭FMResultSet,因为相关的数据库关闭时,FMResultSet也会被自动关闭。

数据参数

通常情况下,你可以按照标准的SQL语句,用?表示执行语句的参数,如:

<span class="line-number">1</span>
INSERT INTO myTable VALUES (?, ?, ?)

然后,可以我们可以调用executeUpdate方法来将?所指代的具体参数传入,通常是用变长参数来传递进去的,如下:

<span class="line-number">1</span><span class="line-number">2</span>
NSString *sql = @"insert into User (name, password) values (?, ?)";[db executeUpdate:sql, user.name, user.password];

这里需要注意的是,参数必须是NSObject的子类,所以象int,double,bool这种基本类型,需要封装成对应的包装类才行,如下所示:

<span class="line-number">1</span><span class="line-number">2</span><span class="line-number">3</span><span class="line-number">4</span>
// 错误,42不能作为参数[db executeUpdate:@"INSERT INTO myTable VALUES (?)", 42];// 正确,将42封装成 NSNumber 类[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]];

线程安全

如果我们的app需要多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安全了。切记不能在多个线程中共同一个FMDatabase对象并且在多个线程中同时使用,这个类本身不是线程安全的,这样使用会造成数据混乱等问题。

使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。在闭包中操作数据库,而不直接参与FMDatabase的管理。

<span class="line-number">1</span><span class="line-number">2</span><span class="line-number">3</span><span class="line-number">4</span><span class="line-number">5</span><span class="line-number">6</span><span class="line-number">7</span><span class="line-number">8</span><span class="line-number">9</span><span class="line-number">10</span><span class="line-number">11</span><span class="line-number">12</span><span class="line-number">13</span><span class="line-number">14</span><span class="line-number">15</span><span class="line-number">16</span><span class="line-number">17</span><span class="line-number">18</span><span class="line-number">19</span><span class="line-number">20</span><span class="line-number">21</span><span class="line-number">22</span><span class="line-number">23</span><span class="line-number">24</span><span class="line-number">25</span><span class="line-number">26</span><span class="line-number">27</span><span class="line-number">28</span>
// 创建,最好放在一个单例的类中FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];// 使用[queue inDatabase:^(FMDatabase *db) {    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];    FMResultSet *rs = [db executeQuery:@"select * from foo"];    while ([rs next]) {        // …    }}];// 如果要支持事务[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];    if (whoopsSomethingWrongHappened) {        *rollback = YES;        return;    }    // etc…    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];}];

工具

为了查看Sqlite中的数据,一个好的图形化界面的数据库管理程序是必不可少的。mysql有phpMyAdmin,那么sqlite呢?

我主要使用的是Firefox的一个名为SQLite Manager的插件,安装此插件后,可以直接打开后缀名为sqlite的数据库文件。SQLite Manager提供一个图形化的界面来执行数据查询或更改操作。如下图所示:

总结

FMDB将SQLite API进行了很友好的封装,使用上非常方便,对于那些使用纯Sqlite API来进行数据库操作的app,可以考虑将其迁移到基于FMDB上,这对于以后数据库相关功能的开发维护,可以提高不少效率。

我在学习fmdb的时候做了一个小工程用于练习,我把它放到github上了。感兴趣的可以自行下载:https://github.com/tangqiaoboy/FmdbSample

祝大家玩得开心。

 Apr 22nd, 2012iOS

原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 考编专业不对口怎么办 北京55中国际部怎么办 初中数学没学好高中怎么办 靴子大了一码怎么办 靴子买大了一码怎么办 马丁靴大了一码怎么办 社保掌上通登录密码忘记怎么办 录微课时忘词怎么办 微课掌上通看不到信息怎么办 五年级学生上课很吵新老师怎么办 跟财务老师吵起来怎么办 qq把微信冻结了怎么办 微信给封号了怎么办 微信久了没登录冻结了怎么办 换手机号了微店怎么办 ai文件置入后都是字怎么办 excel加载项被禁用了怎么办 被期刊网骗了怎么办 发表的文章不想被收录怎么办? 农村长说的眼睛害了怎么办 普通党员不认同领导的决定怎么办 大学读不下去了怎么办 教师因病长期不能上班怎么办 长按win键黑屏了怎么办 巡视组巡视出问题后续怎么办 货运资格证两次没继续教育怎么办 电子注册备案表学信网查不到怎么办 学信网学籍档案没照片怎么办 信访局不给答复怎么办 发票跳了一个号怎么办 报税用的ca证书怎么办 报税u盘丢了怎么办 地税ca证书丢了怎么办 深圳ca证书丢了怎么办 武汉国税报税证书过期怎么办 江苏大学专业选修课挂了怎么办 电信翼企享福卡怎么办 教育部学籍在线验证报告过期怎么办 身份证被别人注册了学信网怎么办 大专文凭查不到学籍该怎么办 学信网上查不到学历怎么办