这是什么?

RelatedDB 是一个轻量级的 Swift 封装,围绕 SQLite 构建。

要求

安装

CocoaPods

CocoaPods 是 Swift 和 Objective-C Cocoa 项目的依赖管理工具。

要将 RelatedDB 库整合到您使用 CocoaPods 的 Xcode 项目中,请在您的 Podfile 文件中引用它,如下所示

pod 'RelatedDB'

Swift Package Manager

Swift Package Manager 是一个用于管理 Swift 代码分发的工具。

一旦您配置了 Package.swift 清单文件,您可以继续将 RelatedDB 包含在同一文件的 dependencies 部分中。

dependencies: [ .package(url: "https://github.com/relatedcode/RelatedDB.git", from: "1.1.5") ]

手动

如果您不喜欢使用任何依赖管理器,您可以手动将 RelatedDB 集成到您的项目中。只需将 RelatedDB/Sources 文件夹中的所有 *.swift 文件复制到您的 Xcode 项目中即可。

用法

连接到数据库

import RelatedDB

let db = RDatabase()

您还可以指定数据库文件名或完整路径。默认文件名是 database.sqlite,默认路径是 Library/Application Support

let db = RDatabase(file: "db.sqlite")
let db = RDatabase(path: "yourpath/db.sqlite")

定义对象

RelatedDB 提供了一个协议,帮助将数据库行作为常规对象来操作。

class User: NSObject, RDObject {

  @objc var userId = 0
  @objc var name = ""
  @objc var age = 0
  @objc var approved = false

  class func primaryKey() -> String {
    return "userId"
  }
}

通过创建上面的 User 类,RelatedDB 将自动为您创建以下 SQLite 表

CREATE TABLE IF NOT EXISTS User (userId INTEGER PRIMARY KEY NOT NULL, name TEXT, age INTEGER, approved INTEGER);

注意:由于所有 RDObject 类属性名称都将在 SQLite 命令中使用,请尽量避免在类定义中使用 SQLite 关键字

插入对象

使用上面的 User 类,创建一个对象看起来像这样

let user = User()

user.userId = 1001
user.name = "John Smith"
user.age = 42
user.approved = false

user.insert(db)

更新对象

可以更新现有对象

user.age = 43

user.update(db)

插入 vs. 更新

如果您不确定数据库中是否已存在某个对象,那么您也可以使用以下方法

user.insertUpdate(db)

它将尝试首先执行 INSERT 命令,如果失败(静默失败),则执行 UPDATE 命令。

此外,您可以使用

user.updateInsert(db)

这将尝试首先执行 UPDATE 命令,如果失败(静默失败),则执行 INSERT 命令。

删除对象

可以删除现有对象

user.delete(db)

获取对象

获取一个对象看起来像这样

let user = User.fetchOne(db, key: 1001)

可以通过以下方式获取多个对象

let users = User.fetchAll(db)

let users = User.fetchAll(db, "age > 40")

let users = User.fetchAll(db, "age = ?", [42])

let users = User.fetchAll(db, "age >= :min AND age <= :max", [":min": 18, ":max": 99])

您还可以使用 limitoffset 参数。

let users = User.fetchAll(db, limit: 10)

let users = User.fetchAll(db, "age > 40", limit: 5, offset: 10)

串行执行,线程安全

数据库写入操作是串行化的。这意味着,Insert、Update 和 Delete 操作将自动一个接一个地执行(由 RelatedDB 管理)。

Fetch 方法是线程安全的。这意味着您将在发起请求的同一线程中获得结果。

注意:您可以从任何线程发起读取和写入操作。

数据类型

RelatedDB 可以管理以下数据类型:BoolInt8Int16Int32Int64IntFloatDoubleStringDateData

日期格式

Date 值将以 ISO 格式化的 String 存储在数据库中。默认格式是 ISO 8601 ("1970-01-01T01:01:01.000Z"),由 ISO8601DateFormatter 类生成。

您还可以使用以下方法指定自己的日期格式

let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

RDDate.custom(formatter)

注意:您只需要在代码库中指定一次日期格式。实际上是在执行任何数据库操作之前。

值字典

虽然将数据库行作为对象管理是一种简单而优雅的方式,但您可能希望将数据作为 Dictionary 来管理。

插入 (使用字典)

将新对象作为字典插入

let values: [String: Any] = ["userId": 1001, "name": "John Smith", "age": 42, "approved": false]

db.insert("User", values)

更新 (使用字典)

将现有对象作为字典更新

let values: [String: Any] = ["userId": 1001, "age": 43]

db.update("User", values)

主键必须包含在值字典中。否则,什么也不会发生。

获取结果 (作为字典)

将一个对象作为字典获取

let user = db.fetchOne("User", key: 1001)

在这种情况下,结果类型将是 [String: Any]

将多个对象作为字典获取

let users = db.fetchAll("User")

let users = db.fetchAll("User", "age > 40")

let users = db.fetchAll("User", "age = ?", [42])

let users = db.fetchAll("User", "age >= :min AND age <= :max", [":min": 18, ":max": 99])

在上述情况下,结果类型将是 [[String: Any]]

转换对象 (为字典)

将现有对象转换为字典

let values = user.values()

日期值 (在字典中)

当使用值字典(插入或更新数据)时,日期值可以作为 Date 或 ISO 格式化的 String 放入字典中。

当获取数据(作为字典)时,日期值将始终在字典中表示为 ISO 格式化的 String

批量更新

您可以通过指定条件来更新多个对象。

let values = ["approved": true]

User.updateAll(db, values, "age >= ? AND age <= ?", [30, 35])

或者,通过指定主键值来更新一个对象。

let values = ["approved": true]

User.updateOne(db, values, key: 1001)

批量删除

您可以通过指定条件来删除多个对象。

User.deleteAll(db, "age >= ? AND age <= ?", [30, 35])

或者,通过指定主键值来删除一个对象。

User.deleteOne(db, key: 1001)

计数对象

您可以通过指定条件来获取对象数量。

let count = User.count(db)

let count = User.count(db, "age > 40")

let count = User.count(db, "age >= ? AND age <= ?", [30, 35])

检查对象

您可以检查对象是否存在(通过指定主键值)。

if (User.check(db, key: 1001)) {
  // do something	
}

或者,您可以检查一组对象是否存在(通过指定条件)。

if (User.check(db, "age >= ? AND age <= ?", [30, 35])) {
  // do something	
}

创建观察者

为了在数据库更改时刷新用户界面,您可以使用数据库观察者。

检查 User 类所有可能的更改将是

let types: [RDObserverType] = [.insert, .update, .delete]

let observerId = User.createObserver(db, types) { method, objectId in
  // do something
}

但是,您可以通过使用条件来缩小更改的数量

let observerId = User.createObserver(db, types, "OBJ.age > 40") { method, objectId in
  // do something
}

此外,您可以使用以下观察者类型:.insert.update.delete,来仅检查特定的数据库更改(分离或组合)。

要获得关于新用户的通知,而不是关于更新和/或删除用户的通知

let observerId = User.createObserver(db, .insert) { method, objectId in
  // do something
}

或者,要获得关于已删除用户的专门通知,看起来像这样

let observerId = User.createObserver(db, .delete) { method, objectId in
  // do something
}

移除观察者

一旦不再需要数据库观察者,您可以使用以下方法将其移除

User.removeObserver(db, observerId)

执行原始 SQL

如果您需要,您可以执行原始 SQL 命令。

db.execute("DELETE FROM User WHERE age = 42;")

删除表,创建表

虽然 SQLite 表是自动创建的,但您也可以手动 DROP 和/或 CREATE 表。

db.dropTable("User")

db.createTable("User")

在这些情况下,还需要首先定义 User 类。

清理数据库

如果您需要,可以使用以下方法销毁并重新创建所有表

db.cleanupDatabase()

错误处理

关键问题将导致 fatalError,所有其他情况将在 Xcode 输出窗口中报告。

您可以使用以下方法更改调试级别

RDDebug.level(.none)

RDDebug.level(.error)

RDDebug.level(.all)

局限性

RelatedDB 工具包处于初始发布阶段。它功能齐全,可以处理大多数工作负载。但是,目前尚不支持某些功能


© Related Code 2022 - 保留所有权利