RXSwift 源码浅析(二) 简述 本文是对上一篇文章的补充,加上对KVO实现的简要分析 和 自己的一些思考,可能会有不够准确的地方还望多多指正,共同学习~~
框架结构 在上篇文章中是从具体实现的角度分析Observable 的使用实现,接下来从一个高一点的角度来分析RXSwift.
效果 无论是Observable,还是KVO,通知,按钮点击….,在本质上我认为可将这一切看为这样一个过程~
以通知为例子, 在程序中某个地方发出了事件(例如键盘弹出),这就是事件源 . 然后这个事件传递 (系统发出键盘弹出的通知). 最后程序的某处响应 了这个事件(比如我们监听到这个通知,然后将控件上移). 我认为RXSwift就是为了让大家更方便的实现这样的过程~
而RXSwift的结构就大概是这样的
结构简图 1,事件源 例如create
函数~
2,响应 为了简洁,我并没有加入资源释放那部分, 具体的可以参照上篇 进行对比的来看, 中介在事件源中接受事件,在响应中输出事件.
接下啦我再以KVO的实现细节 再来展示一下这个结构~~
KVO实现细节 下面是一段日常使用RXSwift的代码~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Test: NSObject { @objc var name:String! } class ViewController: UIViewController { @objc var obj:Test! var disposeBag = DisposeBag() override func viewDidLoad() { super.viewDidLoad() obj = Test() obj.rx.observe(String.self, #keyPath(Test.name)).subscribe { (eve) in print(eve) }.disposed(by: self.disposeBag) } }
事件源 rx 首先第一步是调用对象的rx属性, rx来源于 对NSObject的扩展协议~
1 2 import class Foundation.NSObject extension NSObject: ReactiveCompatible { }
协议实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public protocol ReactiveCompatible { associatedtype CompatibleType // 类属性 和 对象属性~ static var rx: Reactive<CompatibleType>.Type { get set } var rx: Reactive<CompatibleType> { get set } } extension ReactiveCompatible { public static var rx: Reactive<Self>.Type { get { return Reactive<Self>.self } set { } } public var rx: Reactive<Self> { get { return Reactive(self) } set { } } }
这里其实是为了将当前对象封装为一个Reactive 结构体
1 2 3 4 5 6 7 public struct Reactive<Base> { public let base: Base public init(_ base: Base) { self.base = base } }
observe 一般我们调用的是这个扩展方法
1 2 3 4 5 6 7 extension Reactive where Base: NSObject { public func observe<E>(_ type: E.Type, _ keyPath: String, options: KeyValueObservingOptions = [.new, .initial], retainSelf: Bool = true) -> Observable<E?> { return KVOObservable(object: base, keyPath: keyPath, options: options, retainTarget: retainSelf).asObservable() } }
observe
方法首先创建一个KVOObservable
对象~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 //YSD--产生KVO的可观察者 fileprivate final class KVOObservable<Element>: ObservableType , KVOObservableProtocol { typealias E = Element? unowned var target: AnyObject var strongTarget: AnyObject? var keyPath: String var options: KeyValueObservingOptions var retainTarget: Bool //初始化方法 init(object: AnyObject, keyPath: String, options: KeyValueObservingOptions, retainTarget: Bool) { self.target = object self.keyPath = keyPath self.options = options self.retainTarget = retainTarget if retainTarget { self.strongTarget = object } } //订阅方法~~~ func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == Element? { let observer = KVOObserver(parent: self) { (value) in if value as? NSNull != nil { observer.on(.next(nil)) return } observer.on(.next(value as? Element)) } return Disposables.create(with: observer.dispose) } } .............. fileprivate protocol KVOObservableProtocol { var target: AnyObject { get } var keyPath: String { get } var retainTarget: Bool { get } var options: KeyValueObservingOptions { get } }
KVOObservable
对象遵守ObservableType
协议,所以可以调用asObsevable()
方法, KVOObservableProtocol
协议限定它持有这些KVO 必须的属性~,因为在本质上,还是调用OC的KVO实现~
动态语言还是爽呀~
订阅方法 订阅时也就是上面重载的方法~ 首先还是创建一个观察者,来持有 事件响应的闭包~
1 2 3 4 5 6 7 let observer = KVOObserver(parent: self) { (value) in if value as? NSNull != nil { observer.on(.next(nil)) return } observer.on(.next(value as? Element)) }
然而事件是从哪里发出的呢~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 fileprivate final class KVOObserver : _RXKVOObserver , Disposable { typealias Callback = (Any?) -> Void var retainSelf: KVOObserver? = nil init(parent: KVOObservableProtocol, callback: @escaping Callback) { #if TRACE_RESOURCES _ = Resources.incrementTotal() #endif super.init(target: parent.target, retainTarget: parent.retainTarget, keyPath: parent.keyPath, options: parent.options.nsOptions, callback: callback) //因为 可观察者并不强引用它,所以通过循环引用 保持自己不被回收 self.retainSelf = self } //只用调用dispose后才会回收,所以大家注意 不要因为偷懒不好好使用disposeBag(๑•ᴗ•๑) override func dispose() { super.dispose() self.retainSelf = nil } deinit { #if TRACE_RESOURCES _ = Resources.decrementTotal() #endif } }
相对应它的父类就是OC实现的~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 @interface _RXKVOObserver () //和weak差不多, 但是weak释放了为变为nil 它不会 会因为野指针的使用而崩溃 @property (nonatomic, unsafe_unretained) id target; @property (nonatomic, strong ) id retainedTarget; @property (nonatomic, copy ) NSString *keyPath; @property (nonatomic, copy ) void (^callback)(id); @end @implementation _RXKVOObserver -(instancetype)initWithTarget:(id)target retainTarget:(BOOL)retainTarget keyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options callback:(void (^)(id))callback { self = [super init]; if (!self) return nil; self.target = target; if (retainTarget) { self.retainedTarget = target; } self.keyPath = keyPath; self.callback = callback; [self.target addObserver:self forKeyPath:self.keyPath options:options context:nil]; return self; } //常规的操作,将监听到的新值作为block参数返回 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { @synchronized(self) { self.callback(change[NSKeyValueChangeNewKey]); } } -(void)dispose { [self.target removeObserver:self forKeyPath:self.keyPath context:nil]; self.target = nil; self.retainedTarget = nil; }
将KVO的newValue作为参数传入 callBack闭包中~
所以RXSwift对于 KVO的实现就比较简单了,观察者既是事件源 也是 中介 总的来说是将 普通的KVO写法 进行封装,纳入自己的体系之下
反思~ 学而不思则罔,思而不学则殆. 所以看完大神的源码一定要反思~ 不然除了框架用的更熟练 跟没看一样~
面向协议 我认为RXSwift就是一个我们学习面向协议编程 (Protocol-oriented programming)的好例子~, 通过协议 我们可以很好的解决继承 带来的种种弊端~
1, 可以实现在OC和Swift不允许的 多继承~ 2, 避免基类受制于子类, 实现依赖倒转, 让子类受制于协议~
在RXSwift中有一些重要的协议ObservableType ,ObserverType ,Disposable
ObservableType1 2 3 4 public protocol ObservableType : ObservableConvertibleType { func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E }
ObserverType1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public protocol ObserverType { associatedtype E func on(_ event: Event<E>) } extension ObserverType { public func onNext(_ element: E) { on(.next(element)) } public func onCompleted() { on(.completed) } public func onError(_ error: Swift.Error) { on(.error(error)) } }
Disposable1 2 3 public protocol Disposable { public func dispose() }
通过这些协议 将各个角色类的行为加以限制, 而各个协议之间是互相对接的,这样即使各个类不相同,只要大家遵守相同的协议,就可以在这个体系下畅通无阻~ . 打个简单的例子就是 弹幕功能
从服务器发来的需要展示的消息是各种各样的(普通弹幕,礼物弹幕,贵族弹幕,管理信息弹幕~~~~),当其实在显示的时候,只需要显示文字和图片而已~ 这样让 消息都遵守可以获取文字图片的协议 ,这样不管发过来什么消息 都可以正常显示~ 当然使用继承 也可以实现,但是若我们要加新的消息类型(礼物火箭),这时继承要改基类 ,乱改基类很有可能会影响到其他子类导致Bug,而协议只需要扩展,或者限定类型的扩展~
当然这不是说让大家不要用继承 ,在RXSwift中也是有继承的~
1 final class AnonymousObserver<ElementType> : ObserverBase<ElementType> {......}
所以我个人是这样认为的,POP这是纲领,不是方案~ 使用的时候要灵活,小范围,少变动的用继承 ,大范围,多变化的用协议
单一责任原则 在搭架子的时候就将 角色责任 区分好~ 就像最上面的图示一样,,避免类兼数值. 这样无论是对Bug的定位,还是对项目架构的贯彻 都是有好处的~(๑•ᴗ•๑)
最少知道原则 也就是耦合度的问题,我觉得大家都知道写代码要 高内聚,低耦合. 但是怎么做呢~ 在RXSwift中是这样做的,也就是POP 各个角色间通过协议沟通(我到目前为止展示出来的方法,基本上都是协议上的方法),而类通过遵守协议对协议内容进行实现. 这样 耦合的就只有协议,而类只专注对协议的实现
结尾 暂时就反思了这么多~然后有内容再补充吧,下篇就写 flatMap 的分析~ 如果老大的需求没下来 应该很快吧~. 文中要有不准确的地方,请多多指正呀(๑•ᴗ•๑)