美文网首页RxSwift学习
RxSwift源码分析(3)——ControlEvent

RxSwift源码分析(3)——ControlEvent

作者: 无悔zero | 来源:发表于2020-10-01 19:07 被阅读0次

ControlEvent其实是比较常见的用来监听UI控件交互的,那么我们来分析它是怎么实现的。我们看以下例子:

let ob = button.rx.controlEvent(.touchUpInside)
ob.subscribe { (reslut) in
    print("点击按钮·")
}.disposed(by: disposeBag)
  1. 首先创建序列,从源码可以看到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 {
    ...
}
  1. 然后就是在外面订阅序列:
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
    }
}

我们还可以看到它是默认在主线程里执行的:

  1. 根据之前的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)
    }
    ...
}
  1. 进入之后我们就看到了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)
        }
    }
}
  1. 然后便是调用外面传进来的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)

我们可以从源码里看到,tapchanged里面都是封装了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))
    }
    ...
}

相关文章

网友评论

    本文标题:RxSwift源码分析(3)——ControlEvent

    本文链接:https://www.haomeiwen.com/subject/qgtvuktx.html