Bindy
只是一个简单的绑定。
安装
请将pod 'Bindy'
添加到你的podfile中,并运行pod install
SPM也受支持。
用法
目前,Bindy有几个基本类型
- Signal - 允许在接收到某些信号时触发回调。
- Observable - 允许观察值的改变。
- ObservableArray - 遵循MutableCollection协议,因此你可以像处理普通数组一样处理它:索引、替换对象、映射、枚举等... 此外,ObservableArray还有一个
updates
信号,它将通知你数组中发生的任何更改,如插入、替换、删除。
Observables 示例(使用属性包装器更新)
@Observable var firstname = "Salvador"
@Observable var age = 54
func setupBindings() {
$age.bind(self) { [unowned self] newAge in
print("Happy \(newAge) birthday, \(firstname)")
}
age = 55
}
请始终在闭包中使用 [unowned owner]
以防止保留周期。
信号和数组样例
let messages: ObservableArray<Message> = []
let newMessage = Signal<Message>()
func setupBindings() {
newMessage.bind(self) { [unowned self] message in
self.messages.append(message)
}
messages.updates.bind(self) { [unowned tableView] updates in
self.tableView.pefrom(updates: updates)
}
}
func handleDidRecieveMessage(_ message: Message) {
newMessage.send(message)
}
}
如果不希望手动解除绑定,则无需手动移除。当你在bind(_ owner: AnyObject...
方法中作为所有者传递的对象释放时,相应的绑定将自动解绑。然而,如果您想手动解绑,只需调用unbind(_ owner: AnyObject)
。Bindy为tableView扩展了一个用于执行更新的函数tableView.perform(updates:...
此外,观察者对象有一个observe(_ owner: AnyObject...
方法,它类似于bind
,但会立即触发回调,这在某些情况下可能更方便。
转换
如果您想要接收已转换类型的事件,您可以在Observables上使用transform
函数,如下:
let speed = Observable(20)
lazy var speedString = speed.transform { "\($0)km/h" }
func setupBindings() {
speedString.observe(self) { [unowned self] speedString in
// speedString = "20km/h"
self.speedLabel.text = speedString
}
}
组合
您可以使用combined(with: ..., transform: ...)
函数将两个Observables类型组合起来。
let firstname = Observable("Maxim")
let lastname = Observable("Kotliar")
let age = Observable(24)
lazy var fullName = firstname
.combined(with: lastname) { "name: \($0) \($1)" }
.combined(with: age) { "\($0), age: \($1)" }
func setupBindings() {
userInfo.observe(self) { [unowned self] info in
// info = "name: Maxim Kotliar, age:24"
self.userInfoLabel.text = info
}
}
对于Observable<Bool>
的组合,Bindy提供了更方便的操作符&&
和||
,所以您可以像常规Bool一样组合Observable<Bool>
,也可以使用!
进行反转。
let isPremiumPurchased = Observable(true)
let isInTrialPeriodEnded = Observable(false)
let isAdsShowForced = Observable(false)
lazy var shouldShowAds = isAdsShowForced || !isPremiumPurchased && isInTrialPeriodEnded
KVO支持
Bindy支持KVO,因此您可以使用简单的下标语法从任何KVO支持的属性创建Observable
,如:
let textField = UITextField()
let text = textField[\.text] // type will be Observable<String?>
text.observe(self) { newText in
print(newText)
}
旧值
对于任何Observable
类型,你可以在闭包中接收到旧值,只需向绑定闭包传递两个参数,第一个参数将是旧值,第二个参数为新值。
let observableString = Observable("test")
observableString.bind(self) { oldString, newString in
print("String changed from \(oldString) to \(newString)")
}
高阶函数
Bindy 包含一些高阶函数
map
- 在任何类型上应用,行为类似于 Swift 的 map。flatMap
- 在可选类型的 Observable 上应用,返回非可选类型的 Signal。compactMap
- 在包含集合的 Observable 上应用,行为类似于 Swift 函数。reduce
- 在包含集合的 Observable 上应用,行为类似于 Swift 函数。filter
- 在包含集合的 Observable 上应用,行为类似于 Swift 函数。