用 FMDB 第三方框架操作 SQLite數據庫

本人有若干成套學習視頻, 可試看! 可試看! 可試看, 重要的事情說三遍 包含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 存儲在本質上并不區(qū)分數據類型
  2. 主鍵(primary key)

  • 自動增長,程序員不需要關心
  1. 外鍵(foreign key)
  • 通過外鍵對應起和其他"表(table)"的關系

開發(fā)數據庫的步驟(關鍵)

  1. 建立數據庫 ->有存儲數據的文件
  2. 創(chuàng)建表->每一張數據表存儲一類數據
  3. 利用 SQL 語句對其進行增刪查改,并在 UI 中顯示

移動應用中使用數據庫的好處

實際上,隨著 4G 網絡的普及以及數據的更新數據加快,這一優(yōu)勢正在慢慢削弱
  1. 將網絡數據存儲在本地,不用每次網絡下載,節(jié)省用戶流量
  2. 對本地數據進行查詢

使用第三方框架 FMDB 來操作 SQLite 數據庫的 Demo

iOS原生的操作數據庫的方法十分繁瑣, 所以一般使用第三方框架來操作SQLite 數據庫.

總體思路導圖

總體思路導圖

在使用的過程中,需要用到一些常用的 SQL 語句,這些語句對于一些非專業(yè)的開發(fā)人員來說,不需要去記憶,我們只需要安裝 navicat 這個軟件,然后會自動生成一些常用的 SQL 命令,我們將其 copy 下來供日后使用

下文即是 demo 的主要步驟

  • 在 pod 中導入 FMDB
  • 在target 中添加FMDatabaseAdditionsVariadic和FMDatabaseVariadic兩個 swift 文件

先介紹一下 FMDBDatabase 類

我們首先要創(chuàng)建一個中間管理層對 FMDBDatabase 類進行一個封裝
這個中間管理層就叫做 FMDBManager
FMDBManager中的代碼

import UIKit
/* 導入 FMDB 框架 (不同的命名空間)*/
import FMDB

class FMDBManager: NSObject {
    
    //--------- 首先創(chuàng)建一個單例(管理工具類) ---------
    static let sharerdManager = FMDBManager()
    
    var db: FMDatabase?
    
    //--------- 創(chuàng)建數據庫 ---------
    func openDB() {
        /* 首先給出一個路徑 */
        
        /* NSSearchPathForDirectoriesInDomains返回的是一個數組,所以要取出最后一個元素才能獲得路徑,否則無法拼接出正確的地址,那么在獲取路徑的時候就獲取不到,造成無法創(chuàng)建數據庫文件 */
        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("數據連接成功")
            //--------- 創(chuàng)建一個表 ---------
            creatTable()
        }else{
            print("數據連接失敗")
        }
    }
    
    
    //--------- 關于FMDBDatabase的使用 ---------
    /* 1. 創(chuàng)建,增刪改 均使用 executeUpdate*/
    /* 2. 查詢使用 executeQuery方法*/
    
    func creatTable() {
        
        //--------- 執(zhí)行 sql 語句(不需要記憶)創(chuàng)建一個表格 ---------
        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表情)都存儲在數據庫中,那么我就可以將每一個表情都看作是一個模型,將模型存儲在數據庫中,先創(chuàng)建一個模型類 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 () {
        /* 執(zhí)行添加數據的 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 {
    /* 先創(chuàng)建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類型的數據 */
        
        
        /* 創(chuàng)建一個可變的數組,數組里面的元素是字典 */
        
        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 類基本一樣,只是多了一個閉包,將我們要執(zhí)行的數據庫操作放到閉包里去實現

  • 同樣需要創(chuàng)建一個中間層的管理類,叫做 FMDBQueueManager 類
    代碼如下

import UIKit
import FMDB

class FMDBQueueManager: NSObject {
    
    //--------- 同樣 ,我們先創(chuàng)建一個管理類的單例 ---------
    static let sharedQueueManager = FMDBQueueManager()
    
    //--------- 我們?yōu)檫@個管理類設置一個屬性,是 FMDBDatabaseQueue 類 ---------
    var dbQueue : FMDatabaseQueue?
    
    //--------- 創(chuàng)建并打開數據庫的方法 ---------
    func openDB () {
        
        /* 首先給出一個路徑 */
        let path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).last!
        /* 將路徑打印出來供調試使用 */
        
        print(path)
        /* 給數據庫起一個名字 */
        let databaseName = "sqliteTestTwo.sqlite"
        /* 拼接路徑 */
        let databasePath = "\(path)/\(databaseName)"
        
        /* 初始化 dbQueue */
        dbQueue = FMDatabaseQueue(path: databasePath)
        
        /* 創(chuàng)建一個表 */
        creatTable ()
        
    }

}

extension FMDBQueueManager {
    func creatTable () {
        /* 給出一個創(chuàng)建表的 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'))"
        
        /* 將執(zhí)行 sql 語句的操作放到閉包中去執(zhí)行 */
        dbQueue?.inDatabase({ (FMDatabase) in
            /* 一定要注意,這里是使用 executeUpdate,而不是 executeQuery */
            try! FMDatabase.executeUpdate(sql, [])
        })
    }
}

  • 那么在模型類中的添加數據的代碼也將改變,EmotionModel 中的代碼如下
    /* 添加數據 */
    func insert () {
        /* 執(zhí)行添加數據的 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類型的數據 */
        
        
        /* 創(chuàng)建一個可變的數組,數組里面的元素是字典 */
        
         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.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容