Swiftlet Data,适用于 Swift 和 SwiftUI

Swiftlet Data 是一套后端工具,旨在快速、轻松地为您的应用程序添加对几种常见数据库和数据格式(例如 SQLiteSPONCloudKit)的支持。

注意:Swiftlet Data 是我们 Action Data 库的替代品,专门设计用于与 SwiftUI 配合使用。此外,还对其他一些功能进行了现代化改造和改进。

支持

如果您发现 SwiftletData 有用,并希望帮助支持其持续开发和维护,请考虑进行少量捐赠,尤其是在商业产品中使用它时。

Buy Me A Coffee

正是通过像您这样的贡献者的支持,我才能继续免费构建、发布和维护高质量、文档完善的 Swift Package,如 SwiftletData

安装

Swift Package Manager (Xcode 11 及以上版本)

  1. 在 Xcode 中,选择 File > Add Package Dependency… 菜单项。
  2. 在对话框中粘贴 https://github.com/Appracatappra/SwiftletData.git
  3. 按照 Xcode 的说明完成安装。

为什么不使用 CocoaPods、Carthage 或其他?

支持多个依赖管理器会使维护库的复杂性和所需时间呈指数级增长。

由于 Swift Package Manager 与 Xcode 11(及更高版本)集成,因此它是未来支持的最简单选择。

概述

Swiftlet Data 提供对数据源的轻量级、低级别访问,以及高级 对象关系管理 (ORM) 支持(使用 Swift 的 CodableEncodableDecodable 协议)。

只需创建一个 Class 来保存您的数据,并使其符合 ADDataTable 协议。在从所需类型的提供程序(SQLiteiCloudSPON)打开数据源后,即可使用 ORM 功能快速 保存更新查询 数据。所有这些都无需学习 Core Data 的开销或麻烦。

例如,如果您有一个符合 ADDataTable 协议的 Category 类的实例,以下单行代码将创建(或更新 schema)所需表格,并将类中的值作为新记录写入表格

let category = Category(...)

// Save data to currently open SQLite database.
ADSQLiteProvider.shared.save(category)

以下代码将在 iCloud 中使用 CloudKit 执行相同的操作

let category = Category(...)

// Save data to the user's private iCloud data store.
ADiCloudProvider.shared.save(category)

您还可以选择保存到您的应用程序的所有用户可见的公共 iCloud 容器

let category = Category(...)

// Save data to the public iCloud data store.
ADiCloudProvider.sharedPublic.save(category)

包含内容

Swiftlet Data 添加了以下功能

Action Codable

Action Codable 控件使用 Swift 的 CodableEncodableDecodable 协议,为几种常见数据库和数据格式(如 SQLiteSPONCloudKit)提供支持,以便在您的数据模型和我们的可移植 ADRecordADRecordSet 格式之间移动信息。

通过 Action CodableSwiftlet Data Providers,将您的数据模型对象构建为简单的 structclass 对象,并从 ADDataTable 继承,然后使用 Action Controls 快速创建、插入、更新、删除和维护底层数据源中的表和记录。例如

import Foundation
import SwiftletUtilities
import SwiftletData

class Category: ADDataTable {
    
    enum CategoryType: String, Codable {
	    case local
	    case web
	}
    
    static var tableName = "Categories"
    static var primaryKey = "id"
    static var primaryKeyType: ADDataTableKeyType = .computedInt
    
    var id = 0
    var added = Date()
    var name = ""
    var description = ""
    var enabled = true
    var highlightColor = UIColor.white.toHex()
    var type: CategoryType = .local
    var icon: Data = UIImage().toData()
    
    required init() {
        
    }
}

这包括对具有嵌套对象、数组和字典的复杂表格以及一对一、一对多和多对多等复杂关系的支持。例如

import Foundation
import SwiftletUtilities
import SwiftletData

struct Address: Codable {
    var addr1 = ""
    var addr2 = ""
    var city = ""
    var state = ""
    var zip = ""
}

class Person: ADDataTable {
    
    static var tableName = "People"
    static var primaryKey = "id"
    static var primaryKeyType = ADDataTableKeyType.autoUUIDString
    
    var id = UUID().uuidString
    var firstName = ""
    var lastName = ""
    var addresses: [String:Address] = [:]
    
    required init() {
        
    }
    
    init(firstName: String, lastName:String, addresses: [String:Address] = [:]) {
        self.firstName = firstName
        self.lastName = lastName
        self.addresses = addresses
    }
}

class Group: ADDataTable {
    
    static var tableName = "Groups"
    static var primaryKey = "id"
    static var primaryKeyType = ADDataTableKeyType.autoUUIDString
    
    var id = UUID().uuidString
    var name = ""
    var people = ADCrossReference<Person>(name: "PeopleInGroup", leftKeyName: "groupID", rightKeyName: "personID")
    
    required init() {
        
    }
    
    init(name: String, people: [Person] = []) {
        self.name = name
        self.people.storage = people
    }
}

Swift Portable Object Notation

Action Codable 还引入了对新的 Swift Portable Object Notation (SPON) 数据格式的支持,该格式允许将复杂的数据模型编码为可移植的文本字符串,该字符串不仅编码属性键和数据,还包括有关编码数据的类型信息。例如,使用上面的 Address 结构体

@obj:Address<state$=`TX` city$=`Seabrook` addr1$=`25 Nasa Rd 1` zip$=`77586` addr2$=`Apt #123`>

可移植、人类可读的字符串格式使用单字符类型指示符对值进行编码,如下所示

此外,嵌入的数组将采用 @array[...] 格式,嵌入的字典将采用 @obj:type<...> 格式。

Swiftlet Data Providers

Swiftlet Data Providers 提供对几种常见数据库和数据格式(如 SQLiteSPONCloudKit)的轻量级、低级别访问。结果作为键/值字典 (ADRecord) 或键/值字典数组 (ADRecordSet) 返回。例如

let provider = ADSQLiteProvider.shared
let record = try provider.query("SELECT * FROM Categories WHERE id = ?", withParameters: [1])
print(record["name"])

此外,Swiftlet Data Providers 使用 Action Codable 控件和符合 ADDataTable 协议的数据模型提供高级 对象关系管理 (ORM) 功能。例如,使用上面介绍的 AddressPersonGroup 数据模型

let addr1 = Address(addr1: "PO Box 1234", addr2: "", city: "Houston", state: "TX", zip: "77012")
let addr2 = Address(addr1: "25 Nasa Rd 1", addr2: "Apt #123", city: "Seabrook", state: "TX", zip: "77586")
    
let p1 = Person(firstName: "John", lastName: "Doe", addresses: ["home":addr1, "work":addr2])
let p2 = Person(firstName: "Sue", lastName: "Smith", addresses: ["home":addr1, "work":addr2])
    
let group = Group(name: "Employees", people: [p1, p2])
try provider.save(group)

创建 PeopleGroupPeopleInGroups SQLite 数据库表(如果需要),并将包含关系的新记录实例插入到数据库中。例如

要从数据库中检索 Group,请使用以下代码

let group = try provider.getRow(ofType: Group.self, forPrimaryKeyValue: "F6DEC3CD-DA62-4A08-A2B6-272E62A7F6E3")

Swiftlet Data Providers 设计为可互换,因此您可以先使用 SQLite 数据库和 ADSQLiteProvider 在本地进行开发,然后再切换到 CloudKit 和 ADiCloudProvider,而无需更改任何其他代码。

此外,Swiftlet Data Providers 可用于将数据从一个源移动到另一个源。例如,使用 ADSQLiteProvider 将来自 Web 的 JSON 数据下载并保存到本地 SQLite 数据库中,只需最少的代码。

Action SQL Parser

ADSQLParser 提供将包含一个或多个 SQL 命令的文本解析为 Swiftlet Data SQL Document Object Model (DOM) 的能力,并用于为不支持原生 SQL 的数据源(例如 CloudKit)提供 SQL 支持。

ADSQLParser 使用 SQLite 的 SQL 语法,目前支持完整 SQL 语言的子集。例如

let sql = """
CREATE TABLE IF NOT EXISTS parts
(
	part_id           INTEGER   PRIMARY KEY,
	stock             INTEGER   DEFAULT 0   NOT NULL,
	description       TEXT      CHECK( description != '' )    -- empty strings not allowed
);
"""

let instructions = try ADSQLParser.parse(sql)
print(instructions)

文档

Package 包含所有功能的完整 DocC 文档