什么是FMDB?
FMDB是iOS平台的SQLite数据库框架,FMDB以OC的方式封装了SQLite的C语言API。对比苹果自带的Core Data框架,更加轻量级和灵活,使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码。并且FMDB提供了多线程安全的数据库操作方法,能有效地防止数据混乱。
如何集成FMDB?
这里我只写swift中的集成方式,Objective-C类似,只是不需要添加Swift extensions和桥接。
GitHub地址:https://github.com/ccgus/fmdb
方式一:
下载后将fmdb-master/src/fmdb和fmdb-master/src/extra/Swift extensions拖入项目中,添加系统库文件libsqlite3.tbd。如下图所示:
方式二:
通过CocoaPods添加,但是不推荐这种方式,因为这不是官方的。
use_frameworks! pod 'FMDB', :git => 'https://github.com/robertmryan/fmdb.git'
FMDB核心类
FMDatabase
: 一个FMDatabase表示一个sqlite数据库,所有对数据库的操作都是通过这个类。
executeStatements
: 执行多条sql。
executeQuery
: 执行查询语句。
executeUpdate
: 执行除查询以外的语句,create, drop, insert, delete, update。
FMDatabaseQueue
: 内部封装FMDatabase和串行queue,用于多线程操作数据库,并且提供事务,建议使用这个。
inDatabase
: 参数是一个闭包,在闭包里面可以获得FMDatabase对象。
inTransaction
: 使用事务。
FMResultSet
: 查询的结果集。
通过字段名称获取字段值。
如何使用FMDB?
一、创建表
使用FMDB和使用AFNetworking类似,最好单独创建一个工具类,使用单例进行数据库操作。
新建JFSQLiteManager类,继承NSObject。在这个类中重写构造方法创建FMDatabaseQueue对象,并创建一张数据表JF_Person。表中有4个字段,分别是id(主键)、name、age、height。
import UIKit class JFSQLiteManager: NSObject { /// 创建单例 static let shareManager = JFSQLiteManager() /// 数据库名称 private let dbName = "person.db" /// FMDatabaseQueue对象,用于操作数据库 let dbQueue: FMDatabaseQueue // 构造方法 override init() { // 获取沙盒路径 let documentPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last! // 拼接数据库完整路径 let dbPath = (documentPath as NSString).stringByAppendingPathComponent(dbName) // 创建FMDatabaseQueue对象,会自动打开数据库,并创建一个串行队列 dbQueue = FMDatabaseQueue(path: dbPath) super.init() // 创建数据表 createTable("JF_Person") } // 创建数据表 - parameter tbName: 表名 private func createTable(tbName: String) { // sql语句 let sql = "CREATE TABLE IF NOT EXISTS \(tbName) ( \n" + "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, \n" + "name TEXT, \n" + "age INTEGER, \n" + "height REAL \n" + ");" // db表示一个数据库 dbQueue.inDatabase { (db) -> Void in // 执行sql语句,创建一张表。返回Bool类型是否创建成功 if db.executeUpdate(sql) { print("建表成功") } else { print("建表失败") } } } }
然后在AppDelegate中调用这个单例,测试我们的代码
JFSQLiteManager.shareManager
显示 建表成功!
二、删除表
在JFSQLiteManager类中实现删除表的方法,删除指定表名的数据表。
// 删除指定数据库 - parameter tbName: 表名 func dropTable(tbName: String) { // sql语句 let sql = "DROP TABLE IF EXISTS \(tbName);" // db表示一个数据库 dbQueue.inDatabase { (db) -> Void in // 执行sql语句,创建一张表。返回Bool类型是否创建成功 if db.executeUpdate(sql) { print("删除表成功") } else { print("删除表失败") } } }
然后在AppDelegate中调用这个方法,测试我们的代码
JFSQLiteManager.shareManager.dropTable("JF_Person")
显示 删除表成功!
三、增加数据
在JFSQLiteManager类中实现添加数据的方法,插入一条测试数据。这里只是测试学习,所以SQL语句就直接写死了。
// 添加数据 func insertData() { // sql语句 let sql = "INSERT INTO JF_Person (name, age, height) VALUES (?, ?, ?);" dbQueue.inDatabase { (db) -> Void in if db.executeUpdate(sql, "7ag", 23, 1.95) { print("插入数据成功") // 获取插入数据的主键 let id = db.lastInsertRowId() print("插入数据的id: \(id)") } } }
然后在AppDelegate中调用这个方法,测试我们的代码
JFSQLiteManager.shareManager.insertData()
显示 插入数据成功 插入数据的id: 1!
四、删除数据
在JFSQLiteManager类中实现删除数据的方法,删除id = 1的数据。这里只是测试学习,所以SQL语句就直接写死了。
// 删除数据 func deleteData() { // sql语句 let sql = "DELETE FROM JF_Person WHERE id = 1;" dbQueue.inDatabase { (db) -> Void in if db.executeUpdate(sql) { print("删除数据成功") } } }
然后在AppDelegate中调用这个方法,测试我们的代码
JFSQLiteManager.shareManager.deleteData()
显示 删除数据成功!
五、修改数据
上面一步我们把添加的数据给删除,所以我们需要再次调用添加数据的方法,添加一条数据以供我们学习测试使用。
在JFSQLiteManager类中实现更新数据的方法,更新id = 1的数据。这里只是测试学习,所以SQL语句就直接写死了。
// 更新数据 func updateData() { // sql let sql = "UPDATE JF_Person SET name = '6ag', age = 24, height = 1.92 WHERE id = 1;" dbQueue.inDatabase { (db) -> Void in if db.executeUpdate(sql) { print("更新数据成功") } } }
然后在AppDelegate中调用这个方法,测试我们的代码
JFSQLiteManager.shareManager.updateData()
显示 更新数据成功 !
六、查找数据
上面增、删、改中,我们执行sql语句的方法都是使用executeUpdate。但是查找数据,我们就必须使用executeQuery了。其实不管是神马操作,改变的基本都是SQL语句而已。这一点比起C语言的sqlite API来说,简直是太方便了。如果对于SQL语句不是很熟悉也没关系,在下已经为各位大神准备好了常用SQL语句:https://blog.6ag.cn/1227.html
在JFSQLiteManager类中实现更新数据的方法,查询JF_Person表中所有记录的id,name,age,height字段的值。这里只是测试学习,所以SQL语句就直接写死了。
// 查询数据 func queryData() { // sql let sql = "SELECT id, name, age, height FROM JF_Person;" dbQueue.inDatabase { (db) -> Void in guard let result = db.executeQuery(sql) else { print("没有查询到数据") return } // 获取查询结果 // next() 表示获取一条记录, 返回true表示获取到记录,false表示没有记录。所以我们使用循环来获取所有查询到的数据 while result.next() { let id = result.intForColumn("id") let name = result.stringForColumn("name") let age = result.intForColumn("age") let height = result.doubleForColumn("height") // 打印出查询到的数据 print("id: \(id), name: \(name), age: \(age), height: \(height)") print("------------") } } }
然后在AppDelegate中调用这个方法,测试我们的代码
JFSQLiteManager.shareManager.queryData()
打印出
id: 1, name: 6ag, age: 24, height: 1.92
------------