swiftUI笔记之WCDB实践
目标
为chatGpt聊天窗口添加支持本地持久化,操作方式分为:
1、新增聊天项,即在chat数据库增加数据 (聊天项列表)
1 | CREATE TABLE "main"."chat" ( |
2、新增会话,即在session数据库中增加数据 (会话列表)
1 | CREATE TABLE "main"."session" ( |
可以类比使用微信的过程,数据进行的本地化存储持久化。
实践
封装文件目录操作
我们先封装一下对文件目录的操作
QFileManage.swift1
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
41import 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
31import 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
34import 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
29import 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())])