平常使用RxSwift时经常用到bind函数,意思是绑定,把监听和响应绑定在一起。它使我们的代码变得更加简洁,非常好用,比如:
//tf序列发送响应时,会作用在label上
//相当于监听textField.text变化,然后响应label.text = textField.text
textField.rx.text.bind(to: label.rx.text)
- 首先把这句代码拆分为三部分:
textField.rx.text
,label.rx.text
,.bind(to: )
。
先来看textField.rx.text
,只是一个普通序列:
extension Reactive where Base: UITextField {
public var text: ControlProperty<String?> {
return value
}
...
}
再来看label.rx.text
,是一个Binder
,也是一个序列:
extension Reactive where Base: UILabel {
public var text: Binder<String?> {
...
}
...
}
public struct Binder<Value>: ObserverType {
...
}
最后把上面两个序列绑定在一起的就是.bind(to: )
,.bind(to: )
函数找出来有很多个,我们看对应类型的就行:
extension ObservableType {
@available(*, deprecated, renamed: "bind(to:)")//原来改名了,差点没找到
public func bindTo<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
return self.subscribe(observer)
}
}
-
.bind(to: )
函数内部其实自己进行了subscribe
,根据RxSwift核心逻辑,将会调用observer
的on
函数,observer
也就是Binder
:
public struct Binder<Value>: ObserverType {
...
public func on(_ event: Event<Value>) {
self._binding(event)
}
...
}
-
self._binding()
是Binder
初始化时保存的私有函数:
public struct Binder<Value>: ObserverType {
public typealias Element = Value
private let _binding: (Event<Value>) -> Void
public init<Target: AnyObject>(_ target: Target, scheduler: ImmediateSchedulerType = MainScheduler(), binding: @escaping (Target, Value) -> Void) {
weak var weakTarget = target
self._binding = { event in
switch event {
case .next(let element):
_ = scheduler.schedule(element) { element in
if let target = weakTarget {
binding(target, element)
}
return Disposables.create()
}
case .error(let error):
bindingError(error)
case .completed:
break
}
}
}
...
}
我们还可以发现后面的调用会在主线程执行:

- 最终在主线程调用
binding(target, element)
,这是Binder
初始化时传过来的闭包:
extension Reactive where Base: UILabel {
/// Bindable sink for `text` property.
public var text: Binder<String?> {
return Binder(self.base) { label, text in
label.text = text
}
}
...
}
- 然后拿到
textField.rx.text
传递过来的text值,调用label.text = text
,这样就完成了绑定。
网友评论