与sqlite比较
本质:sqlite。SwiftSqlite是swift的封装。类似FMDB是OC的封装。
易于使用原因:sql语句转化为对应关于对象操作。其实对应的是相应的sql语句。
使用
初始化
- 数据库,表,表结构,初始化
public static let standard = PTDownloadTable() //数据库 private var db: Connection? //表 private let downLoadFile = Table("downLoadFile") // 列(数据库表结构) private let id = Expression("id") private let fielUrl = Expression ("fielUrl") private let downLoadState = Expression ("downLoadState") private let isBrowse = Expression ("isBrowse") private let destinationFielUrl = Expression ("destinationFielUrl") private let downLoadTime = Expression ("downLoadTime") private let type = Expression ("type") private let title = Expression ("title") private let brief = Expression ("biref") init () { // self.db = createDB() createTable() }复制代码
- 创建数据库并连接
/// 创建数据库,并连接 private func createDB() -> Connection? { //获取doc路径 let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first! //如果不存在的话,创建一个名为db.sqlite3的数据库,并且连接数据库 do { let db = try Connection("\(path)/db.sqlite3") print("✅数据库创建并连接成功:\(db)") return db } catch { print("?数据库创建并连接失败:\(error)") return nil } }复制代码
- 创建表
/// 创建下载表,已经存在不会再次创建 private func createTable() { if let db = self.db { do { try db.run(downLoadFile.create(block: { (t) in t.column(id, primaryKey: .autoincrement) t.column(fielUrl, defaultValue: "") t.column(downLoadState, defaultValue: "0") t.column(isBrowse, defaultValue: false) t.column(destinationFielUrl, defaultValue: "") t.column(downLoadTime, defaultValue: "") t.column(type, defaultValue: "") t.column(title, defaultValue: "") t.column(brief, defaultValue: "") })) print("✅下载列表创建成功") } catch { print("?下载列表创建失败:\(error)") } } }复制代码
注意: 第一次创建成功,之后不会再次创建。
增
/// 增加记录 public func insertOne(_ fileModel: PTDownLoadModel) { if let db = self.db { let insertDownLoadModel = downLoadFile.insert(fielUrl <- fileModel.fielUrl, downLoadState <- fileModel.downLoadState, isBrowse <- fileModel.isBrowse, destinationFielUrl <- fileModel.destinationFielUrl, downLoadTime <- fileModel.downLoadTime) do { try db.run(insertDownLoadModel) print("✅增加成功") } catch { print("?增加失败:\(error)") } } }复制代码
查
/// 查询多条记录 public func queryManyRecord() -> [PTDownLoadModel]? { var array: [PTDownLoadModel] = [] if let db = self.db { do { for fileModel in try db.prepare(downLoadFile) { let downLoadModel = PTDownLoadModel() downLoadModel.fielUrl = fileModel[fielUrl] downLoadModel.downLoadState = fileModel[downLoadState] downLoadModel.isBrowse = fileModel[isBrowse] downLoadModel.destinationFielUrl = fileModel[destinationFielUrl] downLoadModel.downLoadTime = fileModel[downLoadTime] downLoadModel.type = fileModel[type] downLoadModel.title = fileModel[title] downLoadModel.brief = fileModel[brief] array.append(downLoadModel) } print("✅查询多条数据成功") return array } catch { print("?查询多条数据失败:\(error)") return nil } } return nil }复制代码
/// 查询单条记录 public func queryOneRecord(_ url: String) -> Bool { if let db = self.db { do { for fileModel in try db.prepare(downLoadFile) { if url == fileModel[fielUrl] { print("✅查询单条数据成功:\(url)") return true } } print("?查询单条数据失败") return false } catch { print("?查询单条数据失败:\(error)") return false } } return false }复制代码
改
///更新单条条记录:下载状态和下载地址 public func updateOneLoadRecord(_ url: String,_ state: String,_ destinationUrl: String,_ loadTime: String,_ typeStr: String,_ titleStr: String,_ briefStr: String) { if let db = self.db { let fileModel = downLoadFile.filter(fielUrl == url) do { if destinationUrl == "" { try db.run(fileModel.update(downLoadState <- state)) } else if loadTime == "" { try db.run(fileModel.update(downLoadState <- state)) } else { //只有真正下载完成,才更新:下载地址和下载时间 try db.run(fileModel.update(downLoadState <- state, destinationFielUrl <- destinationUrl, downLoadTime <- loadTime, type <- typeStr, title <- titleStr, brief <- briefStr)) } print("✅更新单条条记录(下载状态和下载地址)数据成功") } catch { print("?更新单条条记录(下载状态和下载地址):数据失败:\(error)") } } }复制代码
删
/// 删除对应数据 func delete(_ url: String) { if let db = self.db { let fileModel = downLoadFile.filter(fielUrl == url) do { try db.run(fileModel.delete()) print("✅删除成功:\(url)") } catch { print("?删除失败:\(url):\(error)") } } }复制代码
表字段更新
/// 更新表 private func updateTableColumn() { if let db = self.db { do { try db.run(downLoadFile.addColumn(userId, defaultValue: "")) print("✅下载列表更新成功") } catch { print("?下载列表更新失败:\(error)") } } }复制代码
一般表字段更新会伴随兼容之前版本问题。就需要考虑数据迁移。
数据迁移
/// 数据迁移(一开始没有userId列数据,更新值) public func dataMigration(_ userIdStr: String) { if let db = self.db { let fileModel = downLoadFile.filter(userId == "") do { try db.run(fileModel.update(userId <- userIdStr)) UserDefaults.standard.setValue(true, forKey: "isMigration") print("✅数据迁移成功") } catch { UserDefaults.standard.setValue(false, forKey: "isMigration") print("?数据迁移失败:\(error)") } } }复制代码
需要把新增列userId的数据过滤出来,然后统一更新。迁移只需一次,所有用了userdefault记录。
/// 是否迁移成功 public func isMigrationSuccess() -> Bool { if let isMigration = UserDefaults.standard.value(forKey: "isMigration") as? Bool { return isMigration } else { return false } }复制代码
判断迁移成功,就不必在迁移。
测试
- 使用模拟器测试,可以在电脑端看到具体路径。把db的路径打印出来就可以。
- 测试工具:【Navicat for SQLite】,打开文件即可。
- 数据更新可以刷新工具,数据同步。