Swift筆記42:WCDB

WCDB(WeChat Database)是由 WeChat 開發(fā)的開源跨平臺數(shù)據(jù)庫框架昂利。它基于 SQLite 和 SQLCipher窝稿,提供高效全面的功能祝闻。WCDB 支持多種編程語言奕谭,包括 Swift、Objective-C贵涵、C++列肢、Java 和 Kotlin。

查看demo

WCDB 優(yōu)點

高性能:針對移動設(shè)備進行了優(yōu)化宾茂,提供快速的查詢執(zhí)行和高效的數(shù)據(jù)存儲瓷马。WCDB的查詢速度比Core Data和FMDB更快。
內(nèi)存使用率低:WCDB在內(nèi)存使用方面比其他數(shù)據(jù)庫更有效率跨晴。
易用性:提供簡單直觀的 API 來執(zhí)行數(shù)據(jù)庫操作欧聘,從而減少開發(fā)工作量。
支持 SQL 和鍵值存儲:通過支持傳統(tǒng)的 SQL 查詢和鍵值存儲系統(tǒng)來提供靈活性端盆。
跨語言兼容性:與 Swift 和 Objective-C 無縫協(xié)作怀骤,適用于 iOS/macOS 項目。
支持SQLCipher加密:WCDB支持數(shù)據(jù)庫加密焕妙,保護用戶的數(shù)據(jù)安全蒋伦。
數(shù)據(jù)庫升級: WCDB的數(shù)據(jù)庫升級很簡單,我們知道不銷毀表的情況下访敌,無法對列直接進行刪除凉敲。
所以WCDB做了這樣的處理:直接在模型綁定里進行列的是否存儲操作,新加列可以在case 里加上寺旺,當(dāng)db.create(table:of:)調(diào)用時會自動在表里新增列爷抓,'刪除'列可在case 里刪除,當(dāng)db.create(table:of:)調(diào)用時會自動在表里忽略此列,但是表里此列并沒有刪除阻塑,且以前此列的值不會刪除

WCDB 缺點

有限的高級功能:可能缺少其他框架提供的一些高級數(shù)據(jù)庫功能蓝撇。
SQLite 依賴項:由于 WCDB 包裝了 SQLite,因此它的功能本質(zhì)上僅限于 SQLite 的功能集陈莽。

GitHub地址
教程文檔
輕量級Browser
安裝Pod
Installing WCDB.swift (2.1.9)
Installing WCDBOptimizedSQLCipher (1.4.6)

創(chuàng)建數(shù)據(jù)庫
private func createDB() -> Database {
    let db = Database(at: path)
    print("創(chuàng)建數(shù)據(jù)庫:", path)
    return db
}
創(chuàng)建表
public func createTable<T: TableCodable>(name: String? = nil, model: T.Type) {
    do {
        try db.create(table: name ?? "\(T.self)", of: T.self)
    } catch {
        debugPrint(error.localizedDescription)
    }
}
添加監(jiān)控
// 全局性能監(jiān)控
Database.globalTracePerformance { tag, path, handleId, sql, cost in
    print("WCDB數(shù)據(jù)庫性能指標: tag \(tag) id \(handleId) at path \(path) takes \(cost) seconds to execute sql \(sql)")
}

// 全局錯誤監(jiān)控
Database.globalTraceError { (error: WCDBError) in
    #if DEBUG
    assert(error.level != .Fatal)
    #endif

    if error.level == .Ignore {
        print("可忽略WCDB數(shù)據(jù)庫信息", error)
    } else {
        print("WCDB數(shù)據(jù)庫錯誤", error)
    }
}
表操作
增加

只是單純的插入數(shù)據(jù),主鍵沖突可能會失敗
如果要支持多參數(shù)和數(shù)組的話渤昌,函數(shù)名重載

    public func insert<T: TableEncodable>(objects:T..., intoTable tableName: String){
        do {
            try db?.insert(objects, intoTable: tableName)
            
        }catch let error {
            debugPrint(error.localizedDescription)
        }
    }
    // 傳入數(shù)組
    public func insert<T: TableEncodable>(objects: [T], intoTable tableName: String) {
        do {
            try db?.insert(objects, intoTable: tableName)

        } catch {
            debugPrint(error.localizedDescription)
        }
    }

插入數(shù)據(jù),當(dāng)數(shù)據(jù)出現(xiàn)沖突時會失敗走搁,而后兩個在主鍵沖突等約束沖突出現(xiàn)時独柑,insertOrReplace會把新數(shù)據(jù)會覆蓋舊數(shù)據(jù)

    public func insertOrReplace<T: TableCodable>(_ objects: T..., tableName: String? = nil, on propertyConvertibleList: [PropertyConvertible]? = nil) {
        let table = db.getTable(named: tableName ?? "\(T.self)", of: T.self)
        do {
            try table.insertOrReplace(objects, on: propertyConvertibleList)
        } catch {
            debugPrint(error.localizedDescription)
        }
    }

執(zhí)行插入或忽略對象。如果當(dāng)前表中已經(jīng)存在相同的主鍵或行id私植,則忽略該對象忌栅。
insertOrIgnore則是會忽略沖突數(shù)據(jù),而不產(chǎn)生錯誤曲稼。

    public func insertOrIgnore<T: TableCodable>(_ objects: T..., tableName: String? = nil, on propertyConvertibleList: [PropertyConvertible]? = nil) {
        let table = db.getTable(named: tableName ?? "\(T.self)", of: T.self)
        do {
            try table.insertOrIgnore(objects, on: propertyConvertibleList)
        } catch {
            debugPrint(error.localizedDescription)
        }
    }

將 table 表內(nèi)索绪,滿足 condition 的數(shù)據(jù),按照 orderList 的方式進行排序贫悄,然后從頭開始第 offset 行數(shù)據(jù)后的 limit 行數(shù)據(jù)按照Condition規(guī)則刪除

let condition: Condition = ExampleItem.Properties.authorNumber <= 3
try? DBManager.shared.db.delete(fromTable: "ExampleItem",
                                where: condition,
                                orderBy: [ExampleItem.Properties.authorNumber.asOrder().order(.descending)],
                                limit: 100)

更改和插入一樣瑞驱,如有存在主鍵并且沖突,更新失敗
根據(jù)條件更新一條數(shù)據(jù)(推薦)

let object = ExampleItem()
object.authorNumber = Int.random(in: 0...10)
object.authorName = "張三"
object.desc = "更新一條數(shù)據(jù)"
try? DBManager.shared.db.update(table: "ExampleItem",
                                on: ExampleItem.Properties.all,
                                with: object,
                                where: ExampleItem.Properties.authorNumber == 1)

更新某個Value

let row: [ColumnCodable] = ["update with row"]
try? DBManager.shared.db.update(table: "ExampleItem",
                                on: ExampleItem.Properties.desc,
                                with: row,
                                where: ExampleItem.Properties.desc == "更新一條數(shù)據(jù)" && ExampleItem.Properties.authorName > 0)
查詢

下例中讀取本地數(shù)據(jù)庫allObjects 窄坦,是讀取所有數(shù)據(jù)
allObjectsA添加規(guī)則查找唤反,condition定義條件,limit條數(shù)鸭津,offset(N)下移N彤侍。

    /// 讀取本地json數(shù)據(jù)
    func readLocalDataBase() {
        do {
            let allObjects: [ExampleItem] = try DBManager.shared.db.getObjects(on: ExampleItem.Properties.all, fromTable: "\(ExampleItem.self)")
            let condition: Condition = ExampleItem.Properties.authorNumber < 50 // && ExampleItem.Properties.authorName == "abc"
            let allObjectsA: [ExampleItem] = try DBManager.shared.db.getObjects(on: ExampleItem.Properties.all, fromTable: "ExampleItem", where: condition, limit: 10, offset: 0)
            let _ = allObjectsA.map {
                print($0.authorNumber ?? 0)
                print($0.authorName ?? "")
            }
            bookArray = allObjectsA
            mTableView.reloadData()
        } catch {}
    }

其它
1 文件與代碼模版,官網(wǎng)有教程曙博。點這里
2 同時WCDB拥刻,Database 和 Table 都能直接發(fā)起事務(wù),事務(wù)提升性能批量處理父泳。而事務(wù)可以保證一段操作的原子性般哼,避免多線程bug。待更新惠窄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蒸眠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子杆融,更是在濱河造成了極大的恐慌楞卡,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蒋腮,居然都是意外死亡淘捡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門池摧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來焦除,“玉大人,你說我怎么就攤上這事作彤”炱牵” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵竭讳,是天一觀的道長创葡。 經(jīng)常有香客問我,道長绢慢,這世上最難降的妖魔是什么灿渴? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮呐芥,結(jié)果婚禮上逻杖,老公的妹妹穿的比我還像新娘。我一直安慰自己思瘟,他們只是感情好荸百,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著滨攻,像睡著了一般够话。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上光绕,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天女嘲,我揣著相機與錄音,去河邊找鬼诞帐。 笑死欣尼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的停蕉。 我是一名探鬼主播愕鼓,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼慧起!你這毒婦竟也來了菇晃?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤蚓挤,失蹤者是張志新(化名)和其女友劉穎磺送,沒想到半個月后驻子,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡估灿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年崇呵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甲捏。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡演熟,死狀恐怖鞭执,靈堂內(nèi)的尸體忽然破棺而出司顿,到底是詐尸還是另有隱情,我是刑警寧澤兄纺,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布大溜,位于F島的核電站,受9級特大地震影響估脆,放射性物質(zhì)發(fā)生泄漏钦奋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一疙赠、第九天 我趴在偏房一處隱蔽的房頂上張望付材。 院中可真熱鬧,春花似錦圃阳、人聲如沸厌衔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽富寿。三九已至,卻和暖如春锣夹,著一層夾襖步出監(jiān)牢的瞬間页徐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工银萍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留变勇,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓贴唇,卻偏偏與公主長得像搀绣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子滤蝠,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容