Show HN: Pledge - 一款轻量级的 Swift 响应式框架(无 Rx 开销)
gokulnair2001/Pledge
main BranchesTags Go to file Code
Folders and files
Name| Name| Last commit message| Last commit date
---|---|---|---
Latest commit
History
30 Commits
.swiftpm/xcode/xcshareddata/xcschemes| .swiftpm/xcode/xcshareddata/xcschemes
Sources| Sources
Tests/PledgeTests| Tests/PledgeTests
.gitignore| .gitignore
CODE_OF_CONDUCT.md| CODE_OF_CONDUCT.md
LICENSE| LICENSE
Package.swift| Package.swift
README.md| README.md
View all files
Repository files navigation
Pledge
Pledge
是一款轻量级、线程安全的 Swift 响应式编程框架,旨在简化状态管理和事件传播,并在应用程序中平衡强大功能与简洁性。其他框架可能会迫使您学习复杂的概念和操作符,但 Pledge
专注于解决开发者日常面临的实际问题:
概述
Pledge
提供了一种简洁、灵活的方式,在 Swift 应用程序中实现观察者模式。它使您能够创建可观察的值,并在值发生更改时通知订阅者,并提供强大的功能,例如:
- 线程安全实现
- 基于优先级的通知
- 可自定义的传递队列
- 批量更新
- 速率限制(节流和防抖)
- 函数式操作符(map, filter 等)
- 全局状态管理
安装
Swift Package Manager
将以下内容添加到您的 Package.swift
文件中:
dependencies: [
.package(url: "https://github.com/gokulnair2001/Pledge.git", from: "1.0.0")
]
核心组件
PLObservable
PLObservable
是 Pledge
的核心,它代表一个值的线程安全容器,该值可以被观察以获取更改。
// 创建一个可观察的字符串
let messageObservable = PLObservable("Hello")
// 订阅更改
let subscription = messageObservable.subscribe { newMessage in
print("Message changed to: \(newMessage)")
}
// 更新值
messageObservable.setValue("Hello World")
PLGlobalStore
PLGlobalStore
为可观察对象提供了一个集中式存储库,充当轻量级的状态管理解决方案。
// 访问共享实例
let store = PLGlobalStore.shared
// 获取或创建一个可观察对象
let userNameObservable = store.string(for: "userName", defaultValue: "Guest")
// 订阅更改
userNameObservable.subscribe { name in
print("User name is now: \(name)")
}
// 从应用程序中的任何位置更新
PLGlobalStore.shared.string(for: "userName").setValue("John")
可观察对象的工作原理
上图说明了 Pledge 中的数据流:
- 一个可观察对象持有一个值,并维护一个订阅者列表
- 当值发生更改时,所有订阅者会按优先级顺序收到通知
- 订阅者可以执行转换器,并指定传递队列以实现线程安全
- 可选的速率限制可以控制通知频率
API 参考
PLObservable
创建一个可观察对象
// 使用一个值初始化
let counter = PLObservable(0)
let isEnabled = PLObservable(true)
let userData = PLObservable(["name": "Guest", "role": "User"])
订阅更改
// 基本订阅
let subscription = observable.subscribe { newValue in
print("Value changed to: \(newValue)")
}
// 不再需要时取消订阅
observable.unsubscribe(subscription)
// 移除所有订阅者
observable.removeAllSubscribers()
控制传递
// 在特定的队列中传递
observable.deliver(on: myCustomQueue).subscribe { value in
// 这个闭包在 myCustomQueue 上运行
}
// 在主队列中传递
observable.deliverOnMain().subscribe { value in
// 这个闭包在主队列中运行
}
// 设置订阅优先级
observable.withPriority(.high).subscribe { value in
// 高优先级订阅者首先收到通知
}
修改值
// 设置一个新值并通知订阅者
observable.setValue(newValue)
// 设置一个值,但不通知
observable.setValue(newValue, notify: false)
// 使用当前值触发通知
observable.notifyObservers()
批量更新
// 开始批量更新
observable.beginUpdates()
// 进行多次更改
observable.setValue(1)
observable.setValue(2)
observable.setValue(3)
// 结束批量更新 - 仅发送一个通知
observable.endUpdates()
速率限制
// 节流:限制为每 0.5 秒一次通知
observable.throttle(for: 0.5).subscribe { value in
// 最多每 0.5 秒调用一次
}
// 防抖:等待更新暂停 0.3 秒
observable.debounce(for: 0.3).subscribe { value in
// 在 0.3 秒没有更新后调用
}
操作符
转换
// 将值映射到不同的类型
let stringCounter = counter.map { "Count: \($0)" }
// Flat-map 到另一个可观察对象
let userDetails = userIdObservable.flatMap { userId in
return fetchUserDetails(userId)
}
// 解包可选值
let optionalValue = PLObservable<String?>("test")
let unwrapped = optionalValue.compactMap()
过滤
// 仅发出通过谓词的值
let evenNumbers = counter.filter { $0 % 2 == 0 }
// 跳过前 N 次发射
let skipFirst = counter.skip(2)
// 仅在值更改时发出
let distinct = values.distinctUntilChanged()
组合
// 合并两个相同类型的可观察对象
let allEvents = userEvents.merge(systemEvents)
// 组合两个可观察对象的最新值
let credentials = username.zip(password)
PLGlobalStore
// 获取/创建类型化的可观察对象
let counter = PLGlobalStore.shared.integer(for: "counter")
let userName = PLGlobalStore.shared.string(for: "userName")
let settings = PLGlobalStore.shared.dictionary(for: "settings")
let items = PLGlobalStore.shared.array(for: "items")
let isEnabled = PLGlobalStore.shared.boolean(for: "isEnabled")
// 移除特定的可观察对象
PLGlobalStore.shared.removeObservable(for: "counter")
// 清除所有可观察对象
PLGlobalStore.shared.removeAllObservables()
使用示例
表单验证
let username = PLObservable("")
let password = PLObservable("")
let isFormValid = PLObservable(false)
// 创建派生状态
let isUsernameValid = username.map { $0.count >= 3 }
let isPasswordValid = password.map { $0.count >= 8 }
// 组合验证
isUsernameValid.subscribe { usernameValid in
isPasswordValid.subscribe { passwordValid in
isFormValid.setValue(usernameValid && passwordValid)
}
}
// 对表单有效性做出反应
isFormValid.subscribe { valid in
submitButton.isEnabled = valid
}
网络状态管理
enum NetworkState {
case idle, loading, success(Data), error(Error)
}
let networkState = PLObservable<NetworkState>(.idle)
// 处理不同的状态
networkState.subscribe { state in
switch state {
case .idle:
// 隐藏指示器
case .loading:
// 显示加载指示器
case .success(let data):
// 使用数据更新 UI
case .error(let error):
// 显示错误消息
}
}
// 加载数据的函数
func fetchData() {
networkState.setValue(.loading)
apiClient.fetchData { result in
switch result {
case .success(let data):
networkState.setValue(.success(data))
case .failure(let error):
networkState.setValue(.error(error))
}
}
}
节流搜索
let searchQuery = PLObservable("")
// 节流以避免过多的 API 调用
searchQuery.throttle(for: 0.3).subscribe { query in
if !query.isEmpty {
performSearch(query)
}
}
许可证
Pledge
在 MIT 许可证下可用。 有关更多信息,请参见 LICENSE 文件。
关于
一款经过深思熟虑设计的 Swift 响应式编程框架。 pledge.framer.website
Topics
swift reactive reactiveswift reactive-programming
Resources
License
Code of conduct
Stars
Watchers
Forks
Releases 1
Packages 0
No packages published
Languages
Footer
Footer navigation
You can’t perform that action at this time.