共享

在你的应用程序的功能和外部持久层(包括用户默认设置、文件系统等)之间即时共享状态。

CI

了解更多

这个库的动机和设计来源于 Point-Free 的许多剧集,这是一个由 Brandon WilliamsStephen Celis 主持的视频系列,探索 Swift 语言中的高级编程主题。

video poster image

概述

这个库提供了一些工具,允许你与应用程序的多个部分以及外部系统(如用户默认设置、文件系统等)共享状态。该工具适用于各种上下文,例如 SwiftUI 视图、@Observable 模型和 UIKit 视图控制器,并且完全可进行单元测试。

作为一个简单的例子,你可以让两个不同的 observable 模型持有一个数据集合,该集合也同步到文件系统

// MeetingsList.swift
@Observable
class MeetingsListModel {
  @ObservationIgnored
  @Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []
}

// ArchivedMeetings.swift
@Observable
class ArchivedMeetingsModel {
  @ObservationIgnored
  @Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []
}

注意

由于 Swift 宏与属性包装器不能很好地配合使用,你必须使用 @ObservationIgnored 注解由 @Observable 模型持有的每个 @Shared。当共享状态更改时,视图仍然会更新,因为 @Shared 处理自己的观察。

如果任何一个模型对 meetings 进行更改,另一个模型将立即看到这些更改。此外,如果磁盘上的文件因外部写入而更改,则 @Shared 的两个实例也将更新以保持最新数据。

自动持久化

@Shared 属性包装器为你提供了一种简洁且一致的方式来持久化应用程序中的任何类型的数据。该库带有 3 种策略:appStoragefileStorageinMemory

appStorage 策略适用于在用户默认设置中存储少量简单数据,例如设置

@Shared(.appStorage("soundsOn")) var soundsOn = true
@Shared(.appStorage("hapticsOn")) var hapticsOn = true
@Shared(.appStorage("userSort")) var userSort = UserSort.name

fileStorage 策略适用于通过将数据序列化为字节来将更复杂的数据类型持久化到文件系统

@Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []

inMemory 策略适用于与整个应用程序全局共享任何类型的数据,但它将在下次应用程序重新启动时重置

@Shared(.inMemory("events")) var events: [String] = []

有关利用库附带的持久化策略以及创建自己的策略的更多信息,请参阅“持久化策略”

随处使用

基本上可以在任何地方使用 @Shared 状态,包括 observable 模型、SwiftUI 视图、UIKit 视图控制器等等。例如,如果你有一个简单的视图需要访问一些共享状态,但不需要 observable 模型的全部功能,那么你可以直接在视图中使用 @Shared

struct DebugMeetingsView: View {
  @Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []
  var body: some View {
    ForEach(meetings) { meeting in
      Text(meeting.title)
    }
  }
}

同样,如果你需要为特定功能使用 UIKit,或者有一个尚不能使用 SwiftUI 的遗留功能,那么你可以直接在视图控制器中使用 @Shared

final class DebugMeetingsViewController: UIViewController {
  @Shared(.fileStorage(.meetingsURL)) var meetings: [Meeting] = []
  // ...
}

为了观察 meetings 的更改以便你可以更新 UI,你可以使用 Shared/publisher 属性或我们 Swift Navigation 库中的 observe 工具。有关更多信息,请参阅 “观察更改”

测试共享状态

即使使用 @Shared 属性包装器的功能与外部存储系统(如用户默认设置和文件系统)交互,它们仍然是可测试的。这是可能的,因为每个测试都获得了一个新的存储系统,该系统被隔离到仅该测试,因此对其进行的任何更改都只能被该测试看到。

有关在使用 @Shared 时如何测试你的功能的更多信息,请参阅 “测试”

文档

此处提供了发布版本和 main 的文档

文章

演示

这个仓库附带了大量示例,以演示如何使用 Sharing 解决常见和复杂的问题。查看 这个 目录以查看所有示例,包括

安装

你可以通过将 Sharing 添加到你的项目中作为包来将其添加到 Xcode 项目中。

https://github.com/pointfreeco/swift-sharing

如果你想在 SwiftPM 项目中使用 Sharing,只需将其添加到你的 Package.swift 中即可

dependencies: [
  .package(url: "https://github.com/pointfreeco/swift-sharing", from: "2.0.0")
]

然后将产品添加到任何需要访问该库的目标

.product(name: "Sharing", package: "swift-sharing"),

社区

如果你想讨论这个库或对如何使用它来解决特定问题有疑问,你可以与 Point-Free 爱好者在多个地方进行讨论

配套库

Sharing 的构建考虑了可扩展性,并且有许多社区支持的库可用于增强你的应用程序

如果你想贡献一个库,请打开一个 PR,其中包含指向它的链接!

许可证

此库在 MIT 许可证下发布。有关详细信息,请参阅 LICENSE