swift-filestore

轻量级键值存储,带有结构化并发 API。

MIT License Package Releases Build Results Swift Version Supported Platforms

为什么选择 swift-filestore?

如果您的应用程序使用 Swift 并发构建,并且需要一个轻量级的键值存储解决方案,那么 swift-filestore 应该是一个不错的选择。

它是一种键值持久化解决方案,在 Swift 的结构化并发(async/await, AsyncSequence)下提供 CRUD 操作和更改流 API。 在底层,它只是将每个对象序列化成一个单独的文件,不涉及数据库或缓存解决方案。这可以保持您的应用程序精简和稳定。

快速开始

通过调用 FileObjectStore.create() 来获取一个实例。 该方法只是在应用程序的 Application Support 目录下创建一个根目录。 在极少数情况下,如果创建目录失败,您可以选择回退到 ObjectStore 的内存实现,或者以您自己的方式处理它。

func createWithFallback() -> ObjectStore {
  do {
    return try FileObjectStore.create()
  } catch {
    return MemoryObjectStore()
  }
}

swift-filestore 不要求开发者为您的数据模型创建新的 struct/类。 例如,要使用 JSON 序列化,只需让您现有的模型符合 JSONDataRepresentable 协议即可。

struct MyModel: Codable, JSONDataRepresentable {
    let id: String
    let value: String
}

let model = MyModel()
try await objectStore.write(key: model.id, namespace: "MyModels", object: model)

对象更改流

swift-filestore 通过 Swift 并发提供了一个对象更改订阅 API。

for try await model in await objectStore.observe(key: id, namespace: "MyModels", objectType: MyModel.self) {
    // process the newly emitted model object
}

自定义序列化/反序列化

如果您正在寻找非 JSON 序列化,您可以如下定义您的自定义序列化/反序列化协议

protocol BinaryDataRepresentable: DataRepresentable {}

extension BinaryDataRepresentable {

  public func serialize() throws -> Data {
    // your custom serialization goes here...
  }
  
  public static func from(data: Data) throws -> Self {
    // your custom deseriazation goes here...
  }
}

struct MyModel: BinaryDataRepresentable {
    let id: String
    let value: String
}

PersistenceLog (持久化日志)

swift-filestore 提供了一个名为 PersistenceLog 的不可变日志记录组件。 它允许开发者将记录存储在磁盘上,并在合适的时候刷新它们。 它可以作为内存日志记录的替代方案,因为应用程序可能随时被用户或系统终止,从而导致数据丢失。

以下代码演示了如何使用 PersistenceLog 存储和发送应用内分析事件

//data model for the analytics log
struct AnalyticsEvent: Codable, JSONDataRepresentable {
    let name: String
    let metaData: String
}

//initialization
let log = try PersistenceLogImpl<AnalyticsEvent>(name: "analytics-log")

//When new event is triggered
try await log.append(event1)

//When it's time to flush and sent to remote server
let events = try await log.flush()
try await networkClient.sendAnalytics(events)