ControlEvent其实是比较常见的用来监听UI控件交互的,那么我们来分析它是怎么实现的。我们看以下例子:
let ob = button.rx.controlEvent(.touchUpInside)
ob.subscribe { (reslut) in
print("点击按钮·")
}.disposed(by: disposeBag)
- 首先创建序列,从源码可以看到
button.rx.controlEvent(.touchUpInside)
创建了一个序列ControlEvent
返回:
let ob = button.rx.controlEvent(.touchUpInside)
extension Reactive where Base: UIControl {
...
public func controlEvent(_ controlEvents: UIControl.Event) -> ControlEvent<()> {
let source: Observable<Void> = Observable.create { [weak control = self.base] observer in
...
}
return ControlEvent(events: source)
}
...
}
可以追溯到ControlEvent
继承了ObservableType
协议:
public struct ControlEvent<PropertyType> : ControlEventType {
...
}
public protocol ControlEventType : ObservableType {
...
}
- 然后就是在外面订阅序列:
ob.subscribe { (reslut) in
...
}
但是从内部源码可以看到,ControlEvent
订阅的时候不是自己进行subscribe
,而是它保存的self._events
:
public struct ControlEvent<PropertyType> : ControlEventType {
public typealias E = PropertyType
let _events: Observable<PropertyType>
public init<Ev: ObservableType>(events: Ev) where Ev.E == E {
self._events = events.subscribeOn(ConcurrentMainScheduler.instance)
}
public func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
return self._events.subscribe(observer)
}
public func asObservable() -> Observable<E> {
return self._events
}
public func asControlEvent() -> ControlEvent<E> {
return self
}
}
我们还可以看到它是默认在主线程里执行的:
- 根据之前的RxSwift核心逻辑将会来到
button.rx.controlEvent(.touchUpInside)
内部创建的序列闭包里,然后可以看到比较重要的代码ControlTarget(control: control, controlEvents: controlEvents)
:
extension Reactive where Base: UIControl {
...
public func controlEvent(_ controlEvents: UIControl.Event) -> ControlEvent<()> {
let source: Observable<Void> = Observable.create { [weak control = self.base] observer in
...
let controlTarget = ControlTarget(control: control, controlEvents: controlEvents) { _ in
observer.on(.next(()))
}
return Disposables.create(with: controlTarget.dispose)
}
.takeUntil(deallocated)
return ControlEvent(events: source)
}
...
}
- 进入之后我们就看到了
control.addTarget(self, action: selector, for: controlEvents)
,就是平常添加控件交互的方法。而它实现的方法selector
是一个私有属性,最终会调用ControlTarget.eventHandler(_:)
final class ControlTarget: RxTarget {
typealias Callback = (Control) -> Void
let selector: Selector = #selector(ControlTarget.eventHandler(_:))
...
init(control: Control, controlEvents: UIControl.Event, callback: @escaping Callback) {
MainScheduler.ensureRunningOnMainThread()
self.control = control
self.controlEvents = controlEvents
self.callback = callback //这里保存外面的闭包
super.init()
//这里实现了控件交互
control.addTarget(self, action: selector, for: controlEvents)
let method = self.method(for: selector)
if method == nil {
rxFatalError("Can't find method")
}
}
...
@objc func eventHandler(_ sender: Control!) {
if let callback = self.callback, let control = self.control {
callback(control)
}
}
}
- 然后便是调用外面传进来的
callback
,接着发送响应observer.on(.next(()))
。根据之前的RxSwift核心逻辑将会回到外面执行响应:
ob.subscribe { (reslut) in
print("点击按钮·")
}.disposed(by: disposeBag)
- 在很多时候我们都不是直接用ControlEvent,比如:
button.rx.tap
.subscribe(onNext: { (event) in
print("常用点击")
}).disposed(by: disposeBag)
textFiled.rx.text.changed
.subscribe { (text) in
print("常用监听输入")
}.disposed(by: disposeBag)
我们可以从源码里看到,tap
和changed
里面都是封装了ControlEvent
:
extension Reactive where Base: UIButton {
/// Reactive wrapper for `TouchUpInside` control event.
public var tap: ControlEvent<Void> {
return controlEvent(.touchUpInside)
}
}
public struct ControlProperty<PropertyType> : ControlPropertyType {
...
public var changed: ControlEvent<PropertyType> {
return ControlEvent(events: self._values.skip(1))
}
...
}