swiftUI笔记之WCDB实践

idurrT

目标

为chatGpt聊天窗口添加支持本地持久化,操作方式分为:

1、新增聊天项,即在chat数据库增加数据 (聊天项列表)

1
2
3
4
5
6
7
CREATE TABLE "main"."chat" (
"sessionId" INTEGER,
"chatId" TEXT,
"content" TEXT,
"isChatgpt" INTEGER,
"createTime" REAL
);

2、新增会话,即在session数据库中增加数据 (会话列表)

1
2
3
4
5
6
CREATE TABLE "main"."session" (
"sessionId" INTEGER,
"title" TEXT,
"createTime" REAL
);

可以类比使用微信的过程,数据进行的本地化存储持久化。

实践

  • 封装文件目录操作
    我们先封装一下对文件目录的操作
    QFileManage.swift

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    import Foundation
    struct QFileManage {
    /// 创建文件夹
    static func createDirectory(at path: String) {
    let isExisted = FileManager.default.fileExists(atPath: path)
    guard !isExisted else { return }
    let url = URL(fileURLWithPath: path)
    do {
    try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true, attributes: nil)
    } catch let error {
    debugPrint("创建文件夹失败!Path: \(path), Error: \(error.localizedDescription)")
    }
    }
    }

    extension QFileManage {
    /// 库目录
    static func libraryDirectory() -> String {
    return NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true).last!
    }

    /// 数据库目录
    static func databaseDirectory() -> String {
    let path = libraryDirectory() + "/database"
    createDirectory(at: path)
    return path
    }

    /// 文档目录
    static func documentsDirectory() -> String {
    return NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).last!
    }

    /// 图片目录
    static func imagesDirectory() -> String {
    let path = documentsDirectory() + "/images"
    createDirectory(at: path)
    return path
    }
    }

  • 模型绑定
    聊天模型:ChatDbModel.swift

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    import Foundation
    import WCDBSwift

    final class ChatDbModel: TableCodable {
    static var tableName: String { "chat" }

    var sessionId: Int64 = 0
    var chatId: String = ""
    var content: String = ""
    var isChatgpt: Bool = false
    var createTime: Date? = nil

    enum CodingKeys: String, CodingTableKey {
    typealias Root = ChatDbModel
    static let objectRelationalMapping = TableBinding(CodingKeys.self)

    case sessionId
    case chatId
    case content
    case isChatgpt
    case createTime
    }

    init(sessionId: Int64, chatId: String, content: String, isChatgpt: Bool, createTime: Date) {
    self.sessionId = sessionId
    self.chatId = chatId
    self.content = content
    self.isChatgpt = isChatgpt
    self.createTime = createTime
    }
    }

    会话模型:SessionDbModel.swift

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    import Foundation
    import WCDBSwift

    final class SessionDbModel: TableCodable {
    static var tableName: String { "session" }

    var sessionId: Int64 = 0
    var title: String? = nil
    var createTime: Date? = nil

    enum CodingKeys: String, CodingTableKey {
    typealias Root = SessionDbModel
    static let objectRelationalMapping = TableBinding(CodingKeys.self)
    case sessionId
    case title
    case createTime
    }

    init(sessionId: Int64, title: String? = nil, createTime: Date? = nil) {
    self.sessionId = sessionId
    self.title = title
    self.createTime = createTime
    }
    }
    extension SessionDbModel {
    static func insert(objects: [SessionDbModel]) {
    do {
    try db?.insert(objects, intoTable: SessionDbModel.tableName)
    } catch let error {
    debugPrint("插入session失败 ->\n\(error.localizedDescription)")
    }
    }
    }

  • 启动时,创建数据库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    import SwiftUI
    import WCDBSwift

    var db: Database?

    @main
    struct tableViewApp: App {
    @AppStorage("appearance") var appearance: String = "system"
    var body: some Scene {
    WindowGroup {
    ContentView().preferredColorScheme(appearance == "system" ? nil : (appearance == "dark" ? .dark : .light))
    }
    }
    init() {
    // 创建数据库
    let path = QFileManage.databaseDirectory() + "/chatgpt.db"
    debugPrint("数据库路径:\(path)")
    db = Database(at:path)
    do {
    // 建表
    try db?.run(transaction: {_ in
    try db?.create(table: SessionDbModel.tableName, of: SessionDbModel.self)
    try db?.create(table: ChatDbModel.tableName, of: ChatDbModel.self)
    })
    } catch let error {
    debugPrint("创建数据库失败!Error: \(error.localizedDescription)")
    }
    }
    }

操作数据库 TODO: viewModel方式操作

  • 新增对话
    1
    SessionDbModel.insert(objects: [SessionDbModel(sessionId: 2, title: "111", createTime: Date())])