美文网首页
用 FMDB 第三方框架操作 SQLite数据库

用 FMDB 第三方框架操作 SQLite数据库

作者: 小冰山口 | 来源:发表于2016-09-24 19:40 被阅读0次

    本人有若干成套学习视频, 可试看! 可试看! 可试看, 重要的事情说三遍 包含Java, 数据结构与算法, iOS, 安卓, python, flutter等等, 如有需要, 联系微信tsaievan.

    SQLite = SQL + Lite(light)
    SQL = Structured Query Language (结构化查询语言)

    SQLite 是一款轻型的数据库, 具有以下特点:

    1. 嵌入式的
    2. 占用资源少, 运行速度快
    3. Mac 已经内置了 SQLite

    关系型数据库的特点

    1. 一个字段(field/col)存储一个值,类似于存储的一个属性
    2. 一行(row)存储一条记录,类似于一个对象
    3. 一个表(table)存储一系列数据,类似于一个对象数组
    4. 多个表之间存在一定的关系,类似于对象之间的关系

    相关术语

    1. 字段(field/col),一个字段存储一个值,可以存储 INTEGER ,REAL ,TEXT ,BLOB,NULL 等五种类型的数据

      • SQLite 存储在本质上并不区分数据类型
    2. 主键(primary key)

    • 自动增长,程序员不需要关心
    1. 外键(foreign key)
    • 通过外键对应起和其他"表(table)"的关系

    开发数据库的步骤(关键)

    1. 建立数据库 ->有存储数据的文件
    2. 创建表->每一张数据表存储一类数据
    3. 利用 SQL 语句对其进行增删查改,并在 UI 中显示

    移动应用中使用数据库的好处

    实际上,随着 4G 网络的普及以及数据的更新数据加快,这一优势正在慢慢削弱
    1. 将网络数据存储在本地,不用每次网络下载,节省用户流量
    2. 对本地数据进行查询

    使用第三方框架 FMDB 来操作 SQLite 数据库的 Demo

    iOS原生的操作数据库的方法十分繁琐, 所以一般使用第三方框架来操作SQLite 数据库.

    总体思路导图

    总体思路导图

    在使用的过程中,需要用到一些常用的 SQL 语句,这些语句对于一些非专业的开发人员来说,不需要去记忆,我们只需要安装 navicat 这个软件,然后会自动生成一些常用的 SQL 命令,我们将其 copy 下来供日后使用

    下文即是 demo 的主要步骤

    • 在 pod 中导入 FMDB
    • 在target 中添加FMDatabaseAdditionsVariadic和FMDatabaseVariadic两个 swift 文件

    先介绍一下 FMDBDatabase 类

    我们首先要创建一个中间管理层对 FMDBDatabase 类进行一个封装
    这个中间管理层就叫做 FMDBManager
    FMDBManager中的代码

    import UIKit
    /* 导入 FMDB 框架 (不同的命名空间)*/
    import FMDB
    
    class FMDBManager: NSObject {
        
        //--------- 首先创建一个单例(管理工具类) ---------
        static let sharerdManager = FMDBManager()
        
        var db: FMDatabase?
        
        //--------- 创建数据库 ---------
        func openDB() {
            /* 首先给出一个路径 */
            
            /* NSSearchPathForDirectoriesInDomains返回的是一个数组,所以要取出最后一个元素才能获得路径,否则无法拼接出正确的地址,那么在获取路径的时候就获取不到,造成无法创建数据库文件 */
            let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last!
            
            /* 打印出存储路径,供查询使用 */
            print(path)
            /* 给数据库起一个名字 */
            let databaseName = "testSqlite.sqlite"
            /* 将数库的名字拼接在路径后面 */
            let databasePath = "\(path)/\(databaseName)"
            
            //--------- 初始化 db ---------
            db = FMDatabase(path: databasePath)
            
            if db!.open() {
                print("数据连接成功")
                //--------- 创建一个表 ---------
                creatTable()
            }else{
                print("数据连接失败")
            }
        }
        
        
        //--------- 关于FMDBDatabase的使用 ---------
        /* 1. 创建,增删改 均使用 executeUpdate*/
        /* 2. 查询使用 executeQuery方法*/
        
        func creatTable() {
            
            //--------- 执行 sql 语句(不需要记忆)创建一个表格 ---------
            let sql = "CREATE TABLE IF NOT EXISTS t_emotion ('id' integer NOT NULL,'png' text NOT NULL,'text' text NOT NULL,PRIMARY KEY('id'))"
            
            // func executeUpdate(sql:String, _ values: AnyObject...) throws
            
            /* 当看到方法中出现 throws 时,必须做异常处理,否则报错 */
            
            try! db?.executeUpdate(sql, [])
        }
    
    }
    
    • 我们将对数据库进行增,删,改的操作都交给 模型来处理
      假定一个应用场景是将所有的表情(例如emoji表情)都存储在数据库中,那么我就可以将每一个表情都看作是一个模型,将模型存储在数据库中,先创建一个模型类 EmotionModel 类

    EmotionModel 类中的代码:

    import UIKit
    
    class EmotionModel: NSObject {
        
        /* 图片 */
        var png:String?
        
        /* 名称 */
        var text:String?
        
        /* kvc 构造函数 */
        init(dict:[String:AnyObject]) {
            
            super.init()
            setValuesForKeysWithDictionary(dict)
            
            
        }
        
        /* 异常处理 */
        override func setValue(value: AnyObject?, forUndefinedKey key: String) {}
    }
    
    // MARK:- 对数据库进行相关的操作
    
    extension EmotionModel {
        
        /* 添加数据 */
        func insert () {
            /* 执行添加数据的 sql 语句 */
            
            let sql = "INSERT INTO 't_emotion' ('png', 'text') values ('\(self.png!)', '\(self.text!)')"
            
            try! FMDBManager.sharerdManager.db?.executeUpdate(sql, [])
            
        }
    }
    
    
    • 这样, 在控制器中,假如我要添加模型 就只需要将 plist 文件中,或者网络加载出的 JSON 数据,字典转模型,再调用模型的对象方法,将模型对象存储到数据库中即可,控制器中的代码如下:
    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            
    //        insertData()
            queryData()
    
        }
    
    }
    
        // MARK:- 操作数据,更新 UI
    
    //--------- 在控制器中我们只管理 UI 的相关操作,从数据库中获取数据我们交给模型来操作 ---------
    
    /* 比如我们想在数据库的表中添加数据,就直接交给模型来做 */
    
    
    extension ViewController {
        /* 先创建100个模型,放到数据库的表中 */
        func insertData() {
            for i in 0..<100 {
                let dict = ["png":"\(i).png", "text":"测试\(i)"]
                
                let emotionModel  = EmotionModel(dict: dict)
                
                emotionModel.insert()
            }
        }
    }
    
    
    • 如果我需要查询数据,就需要使用到另外一个方法: executeQuery,这个方法是有返回值的,返回值是一个 FMResultSet 对象,假设我们现在有一个应用场景是将数据库中的所有数据打印出来,那么我们就在模型类中提供一个类方法,供外界调用

    EmotionModel 类中的补充代码

     class func query ()->[[String : AnyObject]] {
            /* 该 sql 语句是选中表中的某一个 row */
            let sql =  "SELECT * FROM t_emotion"
            /* executeQuery方法的返回值是一个FMResultSet类型的数据 */
            
            
            /* 创建一个可变的数组,数组里面的元素是字典 */
            
            var dataArray : [[String : AnyObject]] = []
            if let result =  try! FMDBManager.sharerdManager.db?.executeQuery(sql, []) {
                while result.next() {
                    let png = result.stringForColumn("png")
                    let text = result.stringForColumn("text")
                    let dict = ["png":png, "text":text]
                    dataArray.append(dict)
                }
            }
            
            return dataArray
        }
    
    • 此时我们在控制器中调用的时候就可以直接调用模型类方法的 API,代码如下:
        func queryData () {
            let dataArray = EmotionModel.query()
            print(dataArray)
        }
    

    再介绍一下 FMDBDatabaseQueue 类

    • 考虑到线程安全问题, 推荐使用 FMDBDatabaseQueue类,其实FMDBDatabaseQueue和 FMDBDatabase 类基本一样,只是多了一个闭包,将我们要执行的数据库操作放到闭包里去实现

    • 同样需要创建一个中间层的管理类,叫做 FMDBQueueManager 类
      代码如下

    import UIKit
    import FMDB
    
    class FMDBQueueManager: NSObject {
        
        //--------- 同样 ,我们先创建一个管理类的单例 ---------
        static let sharedQueueManager = FMDBQueueManager()
        
        //--------- 我们为这个管理类设置一个属性,是 FMDBDatabaseQueue 类 ---------
        var dbQueue : FMDatabaseQueue?
        
        //--------- 创建并打开数据库的方法 ---------
        func openDB () {
            
            /* 首先给出一个路径 */
            let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last!
            /* 将路径打印出来供调试使用 */
            
            print(path)
            /* 给数据库起一个名字 */
            let databaseName = "sqliteTestTwo.sqlite"
            /* 拼接路径 */
            let databasePath = "\(path)/\(databaseName)"
            
            /* 初始化 dbQueue */
            dbQueue = FMDatabaseQueue(path: databasePath)
            
            /* 创建一个表 */
            creatTable ()
            
        }
    
    }
    
    extension FMDBQueueManager {
        func creatTable () {
            /* 给出一个创建表的 sql 语句 */
            let sql = "CREATE TABLE IF NOT EXISTS t_emotion ('id' integer NOT NULL,'png' text NOT NULL,'text' text NOT NULL,PRIMARY KEY('id'))"
            
            /* 将执行 sql 语句的操作放到闭包中去执行 */
            dbQueue?.inDatabase({ (FMDatabase) in
                /* 一定要注意,这里是使用 executeUpdate,而不是 executeQuery */
                try! FMDatabase.executeUpdate(sql, [])
            })
        }
    }
    
    
    • 那么在模型类中的添加数据的代码也将改变,EmotionModel 中的代码如下
        /* 添加数据 */
        func insert () {
            /* 执行添加数据的 sql 语句 */
            
            let sql = "INSERT INTO 't_emotion' ('png', 'text') values ('\(self.png!)', '\(self.text!)')"
            FMDBQueueManager.sharedQueueManager.dbQueue?.inDatabase({ (FMDatabase) in
                try! FMDatabase.executeUpdate(sql, [])
            })
        }
    
    • 控制器中的代码完全不需要变化
    • 在模型类中,查询数据库的代码也需要作出改变,代码如下:
    class func query ()->[[String : AnyObject]] {
            /* 该 sql 语句是选中表中的某一个 row */
            let sql =  "SELECT * FROM t_emotion"
            /* executeQuery方法的返回值是一个FMResultSet类型的数据 */
            
            
            /* 创建一个可变的数组,数组里面的元素是字典 */
            
             var dataArray : [[String : AnyObject]] = []
         FMDBQueueManager.sharedQueueManager.dbQueue?.inDatabase({ (FMDatabase) in
                if let result = try! FMDatabase?.executeQuery(sql, []) {
                    while result.next() {
                        let png = result.stringForColumn("png")
                        let text = result.stringForColumn("text")
                        let dict = ["png":png, "text":text]
                        dataArray.append(dict)
                    }
                }
            })
            
            return dataArray
        }
    

    运行结果如下

    运行结果

    PS. 本人有若干成套学习视频, 包含Java, 数据结构与算法, iOS, 安卓, python, flutter等等, 如有需要, 联系微信tsaievan.

    相关文章

      网友评论

          本文标题:用 FMDB 第三方框架操作 SQLite数据库

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