RxSwift-UITextField事件监听源码分析

UITextField是常用的控件。RxSwiftUITextField的事件.valueChanged, .editingDidBegin, .editingChanged, .editingDidEnd, .editingDidEndOnExit进行封装。
使用方法如下:

  textFiled.rx.text
            .subscribe(onNext: { (text) in
                print("打印: \(text)") // block_1
        })

运行代码:会默认执行一次block_1闭包。
如果textFiled.text = "Jensen"代码,并不会执行block_1闭包。它是怎么实现的呢?
带着疑问,我们进入源码。

textFiled.rx.text做了什么?

public var text: ControlProperty {
        return value
    }

返回的是一个ControlProperty对象,下图是它的继承关系:

ControlProperty.png

通过她的继承关系,我们知道ControlProperty是个可观察序列,也可以作为观察者。

代码中返回了value:

  public var value: ControlProperty {
        return base.rx.controlPropertyWithDefaultEvents(
            getter: { textField in
                textField.text
            },
            setter: { textField, value in
                // This check is important because setting text value always clears control state
                // including marked text selection which is imporant for proper input 
                // when IME input method is used.
                if textField.text != value {
                    textField.text = value
                }
            }
        )
    }

调用base.rx.controlPropertyWithDefaultEvents方法,参数是UITextField.textgettersetter方法

internal func controlPropertyWithDefaultEvents(
        editingEvents: UIControl.Event = [.allEditingEvents, .valueChanged],
        getter: @escaping (Base) -> T,
        setter: @escaping (Base, T) -> Void
        ) -> ControlProperty {
        return controlProperty(
            editingEvents: editingEvents,
            getter: getter,
            setter: setter
        )
    }

调用controlProperty方法初始化:

public func controlProperty(
        editingEvents: UIControl.Event,
        getter: @escaping (Base) -> T,
        setter: @escaping (Base, T) -> Void
    ) -> ControlProperty {
        let source: Observable = Observable.create { [weak weakControl = base] observer in
                guard let control = weakControl else {
                    observer.on(.completed)
                    return Disposables.create()
                }

                observer.on(.next(getter(control)))

                let controlTarget = ControlTarget(control: control, controlEvents: editingEvents) { _ in
                    if let control = weakControl {
                        observer.on(.next(getter(control)))
                    }
                }
                
                return Disposables.create(with: controlTarget.dispose)
            }
            .takeUntil(deallocated)

        let bindingObserver = Binder(base, binding: setter)

        return ControlProperty(values: source, valueSink: bindingObserver)
    }

controlProperty首先创建一个可观察序列source(本文将其命名为source_1,本文中再次出现source_1指的就是这个地方创建的这个可观察序列)。创建序列的逻辑实现可查看RxSwift核心逻辑分析,本文不在赘述。
let bindingObserver = Binder(base, binding: setter)创建一个Binder观察者.

public init(_ 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
            }
        }
    }

Binder观察者中保存了target_binding闭包。

·ControlProperty初始化方法保存了_values_valueSink

 public init(values: Values, valueSink: Sink) where Element == Values.Element, Element == Sink.Element {
        self._values = values.subscribeOn(ConcurrentMainScheduler.instance)
        self._valueSink = valueSink.asObserver()
    }

_valueSink就是上述创建的观察者let bindingObserver = Binder(base, binding: setter)
_values保存的是subscribeOn对象,

    public func subscribeOn(_ scheduler: ImmediateSchedulerType)
        -> Observable {
        return SubscribeOn(source: self, scheduler: scheduler)
    }

final private class SubscribeOn: Producer {
    let source: Ob
    let scheduler: ImmediateSchedulerType
    
    init(source: Ob, scheduler: ImmediateSchedulerType) {
        self.source = source
        self.scheduler = scheduler
    }
}

SubscribeOn保存了values,即是上述创建的source_1

上面就是textFiled.rx.text做的事情,就是创建了一个中间层ControlProperty,保存了一个可观察序列source_1,和它的观察者对象_valueSink

WechatIMG72.jpeg

订阅方法subscribe

结合RxSwift核心逻辑分析,ControlProperty重写了subscribe(observer)方法,序列的订阅会调用到ControlPropertysubscribe(observer)

 public func subscribe(_ observer: Observer) -> Disposable where Observer.Element == Element {
        return self._values.subscribe(observer)
    }

self._valuesSubscribeOn对象,那么self._values.subscribe等价于SubscribeOn.subscribe
根据RxSwift核心逻辑分析,会调用到SubscribeOn.run方法,然后调用sink.run()

func run() -> Disposable {
        let disposeEverything = SerialDisposable()
        let cancelSchedule = SingleAssignmentDisposable()
        
        disposeEverything.disposable = cancelSchedule
        
        let disposeSchedule = self.parent.scheduler.schedule(()) { _ -> Disposable in
            let subscription = self.parent.source.subscribe(self)
            disposeEverything.disposable = ScheduledDisposable(scheduler: self.parent.scheduler, disposable: subscription)
            return Disposables.create()
        }

        cancelSchedule.setDisposable(disposeSchedule)
    
        return disposeEverything
    }

self.parent.source.subscribe(self),self.parentSubscribeOn,SubscribeOn.source正是上面创建的source_1, 根据RxSwift核心逻辑分析,调用可观察序列的subscribe,会执行可观察序列创建时传入的逃逸闭包,

let source: Observable = Observable.create { [weak weakControl = base] observer in
                guard let control = weakControl else {
                    observer.on(.completed)
                    return Disposables.create()
                }

                observer.on(.next(getter(control)))

                let controlTarget = ControlTarget(control: control, controlEvents: editingEvents) { _ in
                    if let control = weakControl {
                        observer.on(.next(getter(control)))
                    }
                }
                
                return Disposables.create(with: controlTarget.dispose)
            }
            .takeUntil(deallocated)

闭包中,首先默认执行observer.on(.next(getter(control))),这也就是为什么第一次订阅会默认调用一次block_1.
然后是ControlTarget的创建

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")
        }
    }

ControlTargetUITextField添加事件,当有时间触发时,就会调用callback,执行外界的block_1。这也就是为什么上述直接对控件赋值,无法执行block_1闭包的原因了,因为直接对控件赋值不属于事件。

总结:

上述是UITextField事件封装及调用的全过程。
简要的说,UITextField事件的封装其实是创建了中间层ControlProperty,ControlProperty保存一个内部可观察序列source_1,及其它的观察者。当调用ControlProperty.subscribe进行订阅时,内部将会转为对内部序列source_1的订阅,对source_1的订阅会执行source_1创建时的尾随闭包,闭包中首先调用一次observer.on,并添加UITextField的事件监听。

t.png

你可能感兴趣的:(RxSwift-UITextField事件监听源码分析)