在iOS开发中使用FMDB
在iOS开发中使用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 在使用上相当方便。以下是一个简单的例子:
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 到你的工程中:
FMDatabase.h FMDatabase.m FMDatabaseAdditions.h FMDatabaseAdditions.m FMDatabasePool.h FMDatabasePool.m FMDatabaseQueue.h FMDatabaseQueue.m FMResultSet.h FMResultSet.m |
建立数据库
建立数据库只需要如下一行即可 , 当该文件不存在时,fmdb 会自己创建一个。如果你传入的参数是空串:@”” ,则 fmdb 会在临时文件目录下创建这个数据库,如果你传入的参数是 NULL,则它会建立一个在内存中的数据库。
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"]; |
打开数据库
使用如下语句,如果打开失败,可能是权限不足或者资源不足。通常打开完操作操作后,需要调用 close 方法来关闭数据库。
if (![db open]) { // error return;}// some operation// ... [db close]; |
执行更新操作
除了 Select 操作之外,其它的都是更新操作。更新操作使用如下方法,如果有错误,可以用 error 参数中获得。
-[FMDatabase executeUpdate:error:withArgumentsInArray:orVAList:] |
执行查询操作
查询操作示例如下。注意:即使操作结果只有一行,也需要先调用 FMResultSet 的 next 方法。
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 提供如下多个方法来获取不同类型的数据:
intForColumn:longForColumn:longLongIntForColumn:boolForColumn:doubleForColumn:stringForColumn:dateForColumn:dataForColumn:dataNoCopyForColumn:UTF8StringForColumnIndex:objectForColumn: |
通常情况下,你并不需要关闭 FMResultSet,因为相关的数据库关闭时,FMResultSet 也会被自动关闭。
数据参数
通常情况下,你可以按照标准的 SQL 语句,用 ? 表示执行语句的参数,如:
INSERT INTO myTable VALUES (?, ?, ?) |
然后,可以我们可以调用 executeUpdate 方法来将 ? 所指代的具体参数传入,通常是用变长参数来传递进去的,如下:
NSString *sql = @"insert into User (name, password) values (?, ?)"; [db executeUpdate:sql, user.name, user.password]; |
这里需要注意的是,参数必须是 NSObject 的子类,所以象 int,double,bool 这种基本类型,需要封装成对应的包装类才行,如下所示:
// 错误,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 的管理。
// 创建,最好放在一个单例的类中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
祝大家玩得开心。
在iOS开发中使用FMDB相关推荐
- ios 开发中 动态库 与静态库的区别
使用静态库的好处 1,模块化,分工合作 2,避免少量改动经常导致大量的重复编译连接 3,也可以重用,注意不是共享使用 动态库使用有如下好处: 1使用动态库,可以将最终可执行文件体积缩小 2使用动态库, ...
- iOS 开发中的多线程
线程.进程 什么是线程.进程 有的人说进程就像是人的脑袋,线程就是脑袋上的头发~~.其实这么比方不算错,但是更简单的来说,用迅雷下载文件,迅雷这个程序就是一个进程,下载的文件就是一个线程,同时下载 ...
- iOS开发中使用[[UIApplication sharedApplication] openURL:]加载其它应用
iOS 应用程序之间(1) 在iOS开发中,经常需要调用其它App,如拨打电话.发送邮件等.UIApplication:openURL:方法是实现这一目的的最简单方法,该方法一般通过提供的url参数的 ...
- iOS开发中各种关键字的区别
1.一些概念 1.浅Copy:指针的复制,只是多了一个指向这块内存的指针,共用一块内存. 深Copy:内存的复制,两块内存是完全不同的, 也就是两个对象指针分别指向不同的内存,互不干涉. 2.atom ...
- Xamarin iOS开发中的编辑、连接、运行
Xamarin iOS开发中的编辑.连接.运行 创建好工程后,就可以单击Xamarin Studio上方的运行按钮,如图1.37所示,对HelloWorld项目进行编辑.连接以及运行了.运行效果如图1 ...
- ios开发中计算代码运算时间_iOS日历、日期、时间的计算
时间和日历的计算在iOS开发中经常看到,经常看到大家在百度,开源中国等搜索这些答案.今天写个简单的时间和日历有关的计算. 获取一个月的总天数 1.获取当月的天数 - (NSInteger)getNum ...
- IOS开发中UIBarButtonItem上按钮切换或隐藏实现案例
IOS开发中UIBarButtonItem上按钮切换或隐藏案例实现案例是本文要介绍的内容,这个代码例子的背景是:导航条右侧有个 edit button,左侧是 back button 和 add bu ...
- iOS开发中标签控制器的使用——UITabBarController
iOS开发中标签控制器的使用--UITabBarController 一.引言 与导航控制器相类似,标签控制器也是用于管理视图控制器的一个UI控件,在其内部封装了一个标签栏,与导航不同的是,导航的管理 ...
- iOS开发中didSelectRowAtIndexPath tap事件响应延迟
iOS开发中didSelectRowAtIndexPath tap事件响应延迟 为UITableViewCell添加tapped事件,代码如下: class VideoViewController: ...
最新文章
- win10下最新MySQL8.0安装与环境配置,Navicat图形化管理工具连接,完整详细可收藏
- Python协程--生成器(通过异常来判断生成器已经结束)
- Python的网络编程[1] - FTP 协议[1] - 使用 pyftplib 建立 FTP 服务器
- iOS夯实:内存管理
- CCNP的实验设备注意事项
- Vue学习笔记之12-前端模块化
- Python之 多重循环
- ceisum加载shp格式的城市白模建筑数据
- excel多个窗口独立显示_细说丨你想要的Excel保护与加密都在这里
- php 通过sendcloud发送邮件附件功能
- 4g运行内存手机还能用多久_手机4G和6G运行内存有多大区别?看完秒懂
- 微信小程序之根据经纬度反查地址
- flutter 打包apk
- ftok函数的作用:
- 计算机后台 鼠标灯不亮,开机一直黑屏键盘鼠标灯不亮
- 惠民工程(最小生成树裸题)
- 文件上传并展示上传文件
- UrlRewritingNet ASP.NET 2.0 中的URL重写(映射)
- html上传文件框架,文件上传 - FastAdmin框架文档 - FastAdmin开发文档
- 【我的Android进阶之旅】Android自定义View来实现解析lrc歌词并同步滚动、上下拖动、缩放歌词、卡拉OK高亮的功能
热门文章
- c或c++语言什么时候用补码来运算,C/C++(基础编码-补码详解)
- java 生成.sh文件,Java 生成Bat或SH文件,调用Sqlldr安插数据到Oracle
- php要掌握的内容,入门PHPer需要掌握的哪些内容?
- html表单下拉美化教程,用javascript实现select的美化的方法
- pytorch dataset dataloader_PyTorch(五)——数据的加载和预处理
- oracle 查询spid,查看数据库session的sid来查杀对应系统进程号spid
- 分区表需要数据备份吗oracle,Oracle 分区表数据的导入与导出(1)
- 前端html5CSS3颜色表示法
- java什么是派生,Java中所有的类都是从( )类或其子类派生而来的。
- symantec 操作 重叠vo_无关收购 谈谈赛门铁克的产品策略思路