在你的应用程序的功能和外部持久层(包括用户默认设置、文件系统等)之间即时共享状态。
这个库的动机和设计来源于 Point-Free 的许多剧集,这是一个由 Brandon Williams 和 Stephen Celis 主持的视频系列,探索 Swift 语言中的高级编程主题。
这个库提供了一些工具,允许你与应用程序的多个部分以及外部系统(如用户默认设置、文件系统等)共享状态。该工具适用于各种上下文,例如 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 种策略:appStorage
、fileStorage
和 inMemory
。
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 解决常见和复杂的问题。查看 这个 目录以查看所有示例,包括
案例研究:许多案例研究演示了该库的内置功能。
API 客户端:一个演示展示了如何通过 API 客户端驱动共享状态。
FirebaseDemo:一个演示展示了如何通过远程 Firebase 配置驱动共享状态。
GRDB 演示:SharingGRDB 是 SwiftData 和 @Query
宏的轻量级替代品,由 Sharing 和 GRDB 驱动。该库包含许多演示。
SyncUps:我们还使用现代化的最佳 SwiftUI 开发实践重建了 Apple 的 Scrumdinger 演示应用程序,包括使用此库共享状态并将其持久化到文件系统。
你可以通过将 Sharing 添加到你的项目中作为包来将其添加到 Xcode 项目中。
如果你想在 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 爱好者在多个地方进行讨论
对于长篇讨论,我们推荐此仓库的 讨论 标签。
对于日常聊天,我们推荐 Point-Free 社区 Slack。
Sharing 的构建考虑了可扩展性,并且有许多社区支持的库可用于增强你的应用程序
@Query
宏的轻量级替代品。如果你想贡献一个库,请打开一个 PR,其中包含指向它的链接!
此库在 MIT 许可证下发布。有关详细信息,请参阅 LICENSE。