序章
在上一篇文章中,已经介绍了最基础的订阅与发布,那么按钮事件的订阅又是如何实现的呢,先看一下demo代码
let _ = addButton.rx.tap.subscribe { [weak self] in
print("+号 next")
self?.count += 1
self?.countString.accept(String(self?.count ?? 0))
} onError: { _ in
} onCompleted: {
print("+号 completed")
} onDisposed: {
print("+号 订阅释放")
}
好了,我们现在来点击addButton看看会输出什么:
+号 next
正确执行了OnNext的闭包方法。细心的你可能会发现onCompleted、onDisposed并没有执行,这个后续写Disposed会详细说明,本文暂不涉及。
第一讲 - rx与tap
在深入了解他的实现之前,我们先需要认识一下rx与tap
走进rx
extension ReactiveCompatible {
public static var rx: Reactive<Self>.Type {
get { Reactive<Self>.self }
set { }
}
public var rx: Reactive<Self> {
get { Reactive(self) }
set { }
}
}
extension NSObject: ReactiveCompatible { }
看源码我们可以看到,rx是ReactiveCompatible协议中的方法,而NSObject遵循了这个协议,使得button可以调用rx方法。
而rx方法的返回的是一个Reactive对象,参数self即为button本身
public struct Reactive<Base> {
public let base: Base
public init(_ base: Base) {
self.base = base
}
}
Reactive就是一个结构体,而在本文中,button即被保存在base中
走进tap
tap方法的实现其实还是Reactive,看源码
extension Reactive where Base: UIButton {
public var tap: ControlEvent<Void> {
controlEvent(.touchUpInside)
}
}
extension Reactive where Base: UIControl {
public func controlEvent(_ controlEvents: UIControl.Event) -> ControlEvent<()> {
//...省略
return ControlEvent(events: source)
}
}
可以看到tap方法实际调用的就是controlEvent方法, 并返回一个ControlEvent对象(ControlEvent遵循ObservableType协议)。
所以序章中的代码可以转换为以下代码:
//创建序列
let ob = Reactive(addButton).controlEvent(.upInside) {
//...省略
return ControlEvent(events: source)
}
//订阅消息
let _ = ob.subscribe { [weak self] in
print("+号 next")
self?.count += 1
self?.countString.accept(String(self?.count ?? 0))
} onError: { _ in
} onCompleted: {
print("+号 completed")
} onDisposed: {
print("+号 订阅释放")
}
第二讲 - 事件转移
你可能好奇为什么标题是事件转移,直接说结果,其实就是RxSwift截胡了addButton的点击事件并在内部实现,进而转换为OnNext事件。接下来我们一步一步看他的具体实现:
- 调用controlEvent方法,创建了source,也就是原理1种所说的创建序列,此时其尾随闭包还未调用,返回controlEvent对象
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)
}
.take(until: deallocated)
return ControlEvent(events: source)
}
- 执行tap.subscribe方法,也就是原理1所说的订阅消息,创建订阅者和订阅闭包
public func subscribe(
onNext: ((Element) -> Void)? = nil,
onError: ((Swift.Error) -> Void)? = nil,
onCompleted: (() -> Void)? = nil,
onDisposed: (() -> Void)? = nil
) -> Disposable {
let disposable: Disposable
//...省略代码
let observer = AnonymousObserver<Element> { event in
switch event {
case .next(let value):
onNext?(value)
//...省略代码
}
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
}
- 紧接着执行self.asObservable().subscribe(observer)方法, 而此时的self即时是一个controlEvent对象,也就是执行controlEvent中的asObservable和subscribe方法
public struct ControlEvent<PropertyType> : ControlEventType {
public typealias Element = PropertyType
let events: Observable<PropertyType>
//将第一步中的source与ConcurrentMainScheduler.instance关联,返回并保存关联后对象
public init<Ev: ObservableType>(events: Ev) where Ev.Element == Element {
self.events = events.subscribe(on: ConcurrentMainScheduler.instance)
}
public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element {
self.events.subscribe(observer)
}
public func asObservable() -> Observable<Element> {
self.events
}
}
- 也就是执行Producer中的subscirbe方法,即创建sink管道,保存第2步中的订阅者。
- 执行sink.run(self)方法,此处self即第1步创建的controlEvent对象,进而执行第1步中的尾随闭包
- 在ControlTarget中,实现了点击方法,并调用了callback,也就是触发了序章中的onNext方法
final class ControlTarget: RxTarget {
typealias Callback = (Control) -> Void
let selector: Selector = #selector(ControlTarget.eventHandler(_:))
weak var control: Control?
var callback: Callback?
init(control: Control, controlEvents: UIControl.Event, callback: @escaping Callback) {
MainScheduler.ensureRunningOnMainThread()
self.control = control
self.controlEvents = controlEvents
self.callback = callback
super.init()
//内部实现了addTarget方法
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!) {
//回调中触发callBack方法
if let callback = self.callback, let control = self.control {
callback(control)
}
}
}
到这里,整个逻辑就梳理完成了。
总结
最后画个图总结一下吧
- 先按照黑色箭头执行
- sink.run回到controlEvent,按照绿色箭头执行
- 最后用户点击事件触发红色箭头