2017-12-31

SQLite.Swift + Codable 簡(jiǎn)單使用

SQLite.Swift 在新版本中支持了 Swift4 的新特性 Codable。SQLite 體積小,是一個(gè)輕量級(jí)的數(shù)據(jù)庫(kù),而 SQLite.Swift 則是用 Swift 對(duì)其進(jìn)行了封裝,而在多數(shù)情況下不必撰寫(xiě) SQL 語(yǔ)句。得益于 Codale,使用 SQLite.Swift 進(jìn)行數(shù)據(jù)持久化將更加簡(jiǎn)單。

下面,我用 SQLite.Swift 構(gòu)建了一個(gè)簡(jiǎn)單的筆記本應(yīng)用,來(lái)熟悉它的基本使用方式。

定義數(shù)據(jù)模型

每一條筆記是一個(gè) NoteItem 類型的結(jié)構(gòu)體。由于我打算讓它的主鍵自增,所以要重寫(xiě) encode 方法。否則,可能就要用 uuid 來(lái)作為主鍵了,有點(diǎn)殺雞用牛刀的感覺(jué)。

struct NoteItem: Codable {
    var id = 0
    var title = ""
    var content = ""
    var timeStamp = 0
    
    init(title: String, content: String, timeStamp: Int) {
        self.title = title
        self.content = content
        self.timeStamp = timeStamp
    }
    
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(title, forKey: .title)
        try container.encode(content, forKey: .content)
        try container.encode(timeStamp, forKey: .timeStamp)
    }
}

因?yàn)橐米栽鲋麈I,就不能自己設(shè)定 id,否則 SQLite 會(huì)報(bào)錯(cuò)。因此要重寫(xiě) encode 方法,不對(duì)對(duì) id 進(jìn)行編碼。而 decode 方法不覆蓋,即使用默認(rèn)方法,把所有屬性全部賦值。

連接數(shù)據(jù)庫(kù)

構(gòu)建一個(gè)數(shù)據(jù)庫(kù)管理類,叫 DataBaseHandler。首先要連接數(shù)據(jù)庫(kù)才能進(jìn)行使用。

class DataBaseHandler {
    var db: Connection!
    func connect() {
        do {
            db = try Connection(getFilePath())
        } catch {
            print("連接數(shù)據(jù)庫(kù)失敗")
        }
    }
    func getFilePath() -> String {
        return NSHomeDirectory() + "/Documents/db.sqlite3"
    }
}

新建 Table

let id = Expression<Int64>("id")
let title = Expression<String>("title")
let content = Expression<String>("content")
let timeStamp = Expression<Int64>("timeStamp")
    
let noteList = Table("NoteList")
func createTable() {
    do {
        try db.run(noteList.create(ifNotExists: true) {
            t in
            t.column(id, primaryKey: .autoincrement)
            t.column(title)
            t.column(content)
            t.column(timeStamp)
        })
    } catch {
        print("建表失敗")
    }
}

這里指定只有在 Table 不存在的時(shí)候才創(chuàng)建。按照數(shù)據(jù)模型添加列,并把 id 指定為自增主鍵以獲得更好的查找性能。

刪除行

作為一個(gè)筆記本應(yīng)用,當(dāng)然要支持滑動(dòng)刪除。

func deleteItem(id: Int) {
    let item = noteList.filter(Int64(id) == self.id)
    do {
        try db.run(item.delete())
    } catch {
        print("刪除失敗")
    }
}

這里先通過(guò) id 查找出元素,再調(diào)用 db.run(item.delete()) 就可以了,等價(jià)于 SQL 語(yǔ)句 DELETE FROM "NoteList" WHERE ("id" = \(id))

插入行

func insert(_ item: NoteItem) -> Int {
    do {
        try db.run(noteList.insert(item))
        return Int(db.lastInsertRowid)
    } catch {
        print(error)
        print("插入失敗")
    }
    return 0
}

由于 id 是數(shù)據(jù)庫(kù)自己生成的,為了讓外界能拿到 id 號(hào)來(lái)進(jìn)行其他的操作,必須把新插入的 id 號(hào)返回??梢杂?db.lastInsertRowid 拿到最新插入的 id,但其實(shí) run() 函數(shù)也是有返回值的,返回值就是 rowid,也可以直接返回。

更新行

筆記本應(yīng)用一個(gè)常見(jiàn)的操作是編輯已有的筆記,因此需要把已有的行更新。也可以刪除舊行再插入新行,但更新的效率更高。

func update(_ item: NoteItem) {
    let oldItem = noteList.filter(Int64(item.id) == self.id)
    do {
        try db.run(oldItem.update(item))
    } catch {
        print("更新失敗")
    }
}

獲取所有行

在筆記本應(yīng)用打開(kāi)時(shí),應(yīng)該展示所有已有的筆記,因此需要將數(shù)據(jù)庫(kù)所有的元素都取出。

func getAllItems() -> [NoteItem] {
    do {
        return try db.prepare(noteList).map({ row in
            return try row.decode()
        })
    } catch {
        print("查找失敗")
    }
    return []
}

數(shù)據(jù)持久化的部分到這里就完成了,剩下的操作就只有構(gòu)建界面了。需要注意的是,應(yīng)該盡量減少操作文件,畢竟讀硬盤(pán)的速度比內(nèi)存操作慢得多,因此各個(gè)界面中應(yīng)該通過(guò)其他方式傳值,而不是都根據(jù)數(shù)據(jù)庫(kù)的內(nèi)容來(lái)更新界面。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,083評(píng)論 4 61
  • 在網(wǎng)上看了這個(gè)故事,主人公亞馬遜CEO杰夫·貝佐斯(Jeff Bezos)。 杰夫·貝佐斯小時(shí),跟著祖父母一起度暑...
    新言漾語(yǔ)閱讀 752評(píng)論 0 1
  • 【pd踐行21天day1 覺(jué)察】今天去上了靜好老師的《正面管教》,期待三天課程后兩個(gè)人一起成長(zhǎng),當(dāng)然課程不是靈丹妙...
    蘭德朱迪閱讀 272評(píng)論 0 1
  • 英語(yǔ)讀音是夸張的 sun太陽(yáng)是三神moon是母 star是四大大 tall他一樣高tall是可以變化的 high是...
    一枚冰兒閱讀 231評(píng)論 0 0
  • 春節(jié)快到了,家人團(tuán)聚的日子是我最頭疼的日子。 十二三歲時(shí),想把成績(jī)單給撕了,尤其是你身邊還有學(xué)霸類的表哥表姐們! ...
    樹(shù)下八只猴閱讀 390評(píng)論 0 0

友情鏈接更多精彩內(nèi)容