AgileDB
- Swift 编写的 SQLite 数据库包装器,无需 SQL 知识即可使用。
- 无需跟踪数据库中使用的列;它是自动的。
- 由于使用了自身的 Thread 子类,因此是完全线程安全的。
- 与 Async/Await 一起工作
- 使用 publish 方法与 Combine 和 SwiftUI 一起工作
安装选项
- Swift 包管理器(推荐)
- CocoaPods
pod AgileDB
- 将所有 .swift 源文件包含到您的项目中
入门指南
- 使用 AgileDB 最好方法是创建一个遵守 DBObject 协议的类或结构。这些实体将自动成为
Codable
。编码的值将保存到数据库中。(以下为支持的值类型) - 或者,您可以使用基于 JSON 字典的低级方法。JSON 节点中支持以下类型:String,Int,Double,Bool,[String],[Int],[Double]。
- 对于任何返回可选值的函数,如果发生错误且无法返回有效值,则该值将为 nil。
DBObject 协议
- DBObject 可以将以下类型保存和读取到数据库中:DBObject, Int, Double, String, Date, Bool, Dictionary, Codable Struct [DBObject], [Int], [Double], [String], [Date], [Dictionary], [Codable Struct](在数据库列中作为JSON文本保存的字典和结构体选择)。所有属性都可为空。对于DBObject属性,键是存储的,以便引用的对象可以独立编辑和保存
- 从数据库读取的Bool属性将解释如下:整数0 = false,任何其他数字均为true。对于字符串值 "1","yes","YES","true",和 "TRUE" 评估为true。
协议定义
public protocol DBObject: Codable {
static var table: DBTable { get }
var key: String { get set }
}
协议方法
/**
Instantiate object and populate with values from the database, recursively if necessary. If instantiation fails, nil is returned.
- parameter db: Database object holding the data.
- parameter key: Key of the data entry.
*/
public init?(db: AgileDB, key: String)
/**
Save the object's encoded values to the database.
- parameter db: Database object to hold the data.
- parameter expiration: Optional Date specifying when the data is to be automatically deleted. Default value is nil specifying no automatic deletion.
- returns: Discardable Bool value of a successful save.
*/
@discardableResult
public func save(to db: AgileDB, autoDeleteAfter expiration: Date? = nil) -> Bool
/**
Remove the object from the database
- parameter db: Database object that holds the data. This does not delete nested objects.
- returns: Discardable Bool value of a successful deletion.
*/
public func delete(from db: AgileDB) -> Bool
/**
Asynchronously instantiate object and populate with values from the database, recursively if necessary.
- parameter db: Database object to hold the data.
- parameter key: Key of the data entry.
- returns: DBObject
- throws: DBError
*/
public static func load(from db: AgileDB, for key: String) async throws -> Self
示例 Struct
import AgileDB
enum Table: String {
static let categories: DBTable = "Categories"
static let accounts: DBTable = "Accounts"
static let people: DBTable = "People"
}
struct Category: DBObject {
static var table: DBTable { return Table.categories }
var key = UUID().uuidString
var accountKey = ""
var name = ""
var inSummary = true
}
// save to database
category.save(to: db)
// save to database, automatically delete after designated date
category.save(to: db, autoDeleteAfter: deletionDate)
// instantiate synchronously
guard let category = Category(db: db, key: categoryKey) else { return }
// instantiate asynchronously
do {
let category = try await Category.load(from: db, for: categoryKey)
// use category
} catch {
}
DBResults 类
- 与 DBObject 元素一起使用
- 使用数据库引用和键实例化该类
- 仅存储键以最小化内存使用
- 数据库发布者返回此类的一个实例
使用
guard let keys = db.keysInTable(Category.table) else { return }
let categories = DBResults<Category>(db: db, keys: keys)
for category in categories {
// use category object
}
for index in 0..<categories.count {
let category = categories[index]
// use category object
}
发布者
- 使用发布者结合订阅者和 SwiftUI
- 按需发送 DBResults 以反映完成的查询和更新结果
- 使用完成来发送可能出现的错误
使用
/**
Returns a Publisher for generic DBResults. Uses the table of the DBObject for results.
- parameter sortOrder: Optional string that gives a comma delimited list of properties to sort by.
- parameter conditions: Optional array of DBConditions that specify what conditions must be met.
- parameter validateObjects: Optional bool that condition sets will be validated against the table. Any set that refers to json objects that do not exist in the table will be ignored. Default value is false.
- returns: DBResultssPublisher
*/
let publisher: DBResultsPublisher<Transaction> = db.publisher()
let _ = publisher.sink(receiveCompletion: { _ in }) { ( results) in
// assign to AnyCancellable property
}
低级方法
键
检查给定的表是否包含给定的键。
let table: DBTable = "categories"
if let hasKey = AgileDB.shared.tableHasKey(table:table, key:"category1") {
// process here
if hasKey {
// table has key
} else {
// table didn't have key
}
} else {
// handle error
}
检查给定的表是否包含所有给定的键。
let table: DBTable = "categories"
if let hasKeys = AgileDB.shared.tableHasAllKeys(table:table, keys:["category1","category2","category3"]) {
// process here
if hasKeys {
// table has all keys
} else {
// table didn't have key
}
} else {
// handle error
}
返回给定表中键的数组。可选地根据根级别的值指定排序顺序
let table: DBTable = "categories"
if let tableKeys = AgileDB.shared.keysInTable(table, sortOrder:"name, date desc") }
// process keys
} else {
// handle error
}
根据给定条件返回从给定表中的键的数组,并按指定的方式进行排序。
/**
All conditions in the same set are ANDed together. Separate sets are ORed against each other. (set:0 AND set:0 AND set:0) OR (set:1 AND set:1 AND set:1) OR (set:2)
Unsorted Example:
let accountCondition = DBCondition(set:0,objectKey:"account",conditionOperator:.equal, value:"ACCT1")
if let keys = AgileDB.keysInTable("table1", sortOrder:nil, conditions:accountCondition) {
// use keys
} else {
// handle error
}
- parameter table: The DBTable to return keys from.
- parameter sortOrder: Optional string that gives a comma delimited list of properties to sort by.
- parameter conditions: Optional array of DBConditions that specify what conditions must be met.
- parameter validateObjects: Optional bool that condition sets will be validated against the table. Any set that refers to json objects that do not exist in the table will be ignored. Default value is false.
- returns: [String]? Returns an array of keys from the table. Is nil when database could not be opened or other error occured.
public func keysInTable(_ table: DBTable, sortOrder: String? = nil, conditions: [DBCondition]? = nil, validateObjects: Bool = false) -> [String]?
*/
let table: DBTable = "accounts"
let accountCondition = DBCondition(set:0,objectKey:"account", conditionOperator:.equal, value:"ACCT1")
if let keys = AgileDB.shared.keysInTable(table, sortOrder: nil, conditions: [accountCondition]) {
// process keys
} else {
// handle error
}
值
数据可以按照此处所示手动设置或检索,或者您的类/结构可以遵循上述文档中的 DBObject 协议,并使用内置的 init 和 save 方法以获得更大的便利性和灵活性。
在表中设置值
let table: DBTable = "Transactions"
let key = UUID().uuidString
let dict = [
"key": key
, "accountKey": "Checking"
, "locationKey" :"Kroger"
, "categoryKey": "Food"
]
let data = try! JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
let json = String(data: data, encoding: .utf8)!
// the key object in the json value is ignored in the setValue method
if AgileDB.shared.setValueInTable(table, for: key, to: json)
// success
} else {
// handle error
}
检索给定键的值
let table: DBTable = "categories"
if let jsonValue = AgileDB.shared.valueFromTable(table, for:"category1") {
// process value
} else {
// handle error
}
if let dictValue = AgileDB.shared.dictValueFromTable(table, for:"category1") {
// process dictionary value
} else {
// handle error
}
删除给定键的值
let table: DBTable = "categories"
if AgileDB.shared.deleteFromTable(table, for:"category1") {
// value was deleted
} else {
// handle error
}
异步检索数据
从版本6.3开始,AgileDB 允许使用 await
的方式异步检索数据。
let db = AgileDB.shared
let table: DBTable = "categories"
do {
let value = try await db.valueFromTable(table, for: key)
} catch {
}
可用的异步方法
- tableHasKey
- tableHasAllKeys
- keysInTable
- valueFromTable
- dictValueFromTable
- sqlSelect
- 加载到DBObject协议中
SQL查询
AgileDB 允许您执行标准的SQL选择以进行更复杂的查询。因为提供的值实际上在表中分散为单独的列,因此可以传递一个标准的SQL语句,并且将返回一个可选的行数组(值数组)。
let db = AgileDB.shared
let sql = "select name from accounts a inner join categories c on c.accountKey = a.key order by a.name"
if let results = db.sqlSelect(sql) {
// process results
} else {
// handle error
}
同步
AgileDB 可在处理任何数据之前启用同步,然后共享同步日志,与其他实例同步。
/**
Enables syncing. Once enabled, a log is created for all current values in the tables.
- returns: Bool If syncing was successfully enabled.
*/
public func enableSyncing() -> Bool
/**
Disables syncing.
- returns: Bool If syncing was successfully disabled.
*/
public func disableSyncing() -> Bool
/**
Read-only array of unsynced tables. Any tables not in this array will be synced.
*/
var unsyncedTables: [String]
/**
Sets the tables that are not to be synced.
- parameter tables: Array of tables that are not to be synced.
- returns: Bool If list was set successfully.
*/
public func setUnsyncedTables(_ tables: [String]) -> Bool
/**
Creates a sync file that can be used on another AgileDB instance to sync data. This is a synchronous call.
- parameter filePath: The full path, including the file itself, to be used for the log file.
- parameter lastSequence: The last sequence used for the given target Initial sequence is 0.
- parameter targetDBInstanceKey: The dbInstanceKey of the target database. Use the dbInstanceKey method to get the DB's instanceKey.
- returns: (Bool,Int) If the file was successfully created and the lastSequence that should be used in subsequent calls to this instance for the given targetDBInstanceKey.
*/
public func createSyncFileAtURL(_ localURL: URL!, lastSequence: Int, targetDBInstanceKey: String) -> (Bool, Int)
/**
Processes a sync file created by another instance of AgileDB This is a synchronous call.
- parameter filePath: The path to the sync file.
- parameter syncProgress: Optional function that will be called periodically giving the percent complete.
- returns: (Bool,String,Int) If the sync file was successfully processed,the instanceKey of the submiting DB, and the lastSequence that should be used in subsequent calls to the createSyncFile method of the instance that was used to create this file. If the database couldn't be opened or syncing hasn't been enabled, then the instanceKey will be empty and the lastSequence will be equal to zero.
*/
public typealias syncProgressUpdate = (_ percentComplete: Double) -> Void
public func processSyncFileAtURL(_ localURL: URL!, syncProgress: syncProgressUpdate?) -> (Bool, String, Int)
修订历史
6.5
- 所有DBObject方法都有async/await的对应版本
6.4
- 更新DBObject编码以支持Dictionary,Codable Struct,[Dictionary],和[Codable Struct]
- 转换为正确的Swift Package
6.3
- 最低swift版本更新到5.5
- 添加了async/await支持
6.2
- 新方法:tableHasAllKeys及其异步等效版本
6.1
- DBObject可以递归地保存和加载DBObject和[DBObject]属性(技术上键被存储,因此引用的对象可以独立地编辑和保存)
6.0
- 新的发布者方法,用于在SwiftUI和Combine中使用。发布者返回新的DBResults对象。所有正在活动的发布者将在发布DBResults时添加、删除或更新键时发送新结果。
- 新的可下标的DBResults对象。只为更好地内存使用而存储键。
- DBObject结构现在可以存储[String],[Int],[Double]和[Date]类型。(不支持嵌套对象。)
5.1
- 使用Xcode 10.2和Swift 5开发和测试
- 引入DBObject协议。请参见下文。
- 调试模式属性已重命名为 isDebugging。
- 现在提供的值中的
key
对象会被忽略,而不是报错。 - 在 keysInTable 方法中的新参数
validateObjects
将会忽略引用不在表中的对象的条件集合。
5.0
- 使用 Xcode 10.1 开发和测试。
- 一些方法已被弃用,并提供了重命名版本以便在使用的点进行清晰地标识。
- 数据可以异步检索。
- 类属性
sharedInstance
已重命名为shared
。 - 方法不再是类级别的,必须通过 db 实例访问。更新到这种方法的一个简单方法是:在现有代码中,将类名后直接添加 .shared。