RXSwift GitHub地址
RXSwift中文文档
RX家族
絮叨:
这篇之所以讲核心逻辑时很仔细(啰嗦),是因为其重要性,必须要给弄懂了!。
简介
全称
ReactiveX for Swift
,是一个简化异步编程的框架,实现了函数响应式编程,事件与对象紧密联系,业务流清晰,便于管理。在RxSwift中,所有异步操作(事件)和数据流均被抽象为可观察序列的概念。
流程为:
创建序列 -> 订阅序列 -> 发送信号 -> 信号接收
简单使用:
- 框架导入: CocoaPods
pod 'RxSwift'
pod 'RxCocoa'
//友情提示 当使用 Moya-ObjectMapper 时,由于此库引用了RxSwift,所以如果有pod 'Moya-ObjectMapper/RxSwift'时,无需再pod 'RxSwift'
写为:
#pod 'RxSwift'
pod 'RxCocoa'
pod 'Moya-ObjectMapper/RxSwift'
在需要使用的类中添加依赖:
import RxCocoa
import RxSwift
- 简单用法:
1 : KVO
class LBPerson:NSObject{
@objc dynamic var name : String = "default"
}
extension LBRegisterViewController{
fileprivate func kvoTest(){
let person = LBPerson.init()
person.rx.observeWeakly(String.self, "name")
.subscribe(onNext: { (value) in
print(value as Any)
})
.disposed(by: disposeBag)
person.name = "lb"
}
}
输出结果:
Optional("lb")
2 : UIButton 事件响应
fileprivate func btnTest(){
let btn = UIButton()
btn.rx.tap.subscribe(onNext: { (_) in
print("事件")
})
}
/*注:tap默认为TouchUpInside. 点进去看源码*/
extension Reactive where Base : UIButton {
/// Reactive wrapper for `TouchUpInside` control event.
public var tap: RxCocoa.ControlEvent<Void> { get }
}
//那么其他类型Event呢: 你看-->
btn.rx.controlEvent(.touchUpOutside).subscribe(onNext: { (_) in
print("事件")
})
输出:
"事件"
3: UITextFiled 键盘内容监听
fileprivate func TFTest(){
let tf = UITextFiled()
let textFieldInputSequence = tf.rx.text.orEmpty.asDriver().throttle(0.4)
textFieldInputSequence.drive(onNext: { (str) in
print("tf值改变-->\(str)")
}).disposed(by: disposeBag)
}
// orEmpty,防空处理.
// throttle节气阀,防暴力触发,参数为时间间隔.
4: UIScrollView ContentOffser监听
let scrollView = UIScrollView()
scrollView.rx.contentOffset
.subscribe(onNext: { [weak self](content) in
print(scrollView.contentOffset.y)
})
.disposed(by: disposeBag)
5: 手势监听
let tap = UITapGestureRecognizer()
let label = UILabel()
label.addGestureRecognizer(tap)
label.isUserInteractionEnabled = true
tap.rx.event.subscribe(onNext: { (tap) in
print(tap.view)
})
.disposed(by: disposeBag)
6: 通知
NotificationCenter.default.rx.notification(UIResponder.keyboardWillShowNotification)
.subscribe(onNext: { (noti) in
print(noti)
})
.disposed(by: disposeBag)
7: 定时器
let timer = Timer.init()
timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
timer.subscribe(onNext: { (num) in
print(num)
}).disposed(by: disposeBag)
8: 网络(URLSession)
let url = URL(string: "https://www.baidu.com")
// 原本写法
// URLSession.shared.dataTask(with: url!) { (data, response, error) in
// print(String.init(data:data!,encoding: .utf8))
// }.resume()
URLSession.shared.rx.response(request: URLRequest(url: url!))
.subscribe(onNext: { (response,data) in
print(response)
}).disposed(by: disposeBag)
这个看起来有点鸡肋,后续文章中会给大家介绍RXSwift结合MOYA使用,从而更优雅的调用网络。先看个效果:
let provider = MoyaProvider<ApiManager>();
provider.request(.login(username: "haha", password: "123456", token: "***")) { (result) in
if result.error == nil{
LBLog(result.value);
}
}
核心逻辑:
重点:重头戏它又来了.
先来个最简单的响应流程:
fileprivate func exploringTest(){
let ob = Observable<Any>.create { (observer) -> Disposable in
observer.onNext("测试")
observer.onCompleted()
return Disposables.create()
}
_ = ob.subscribe(onNext: { (text) in
print("订阅到:\(text)")
}, onError: { (error) in
print("error:\(error)")
}, onCompleted: {
print("完成")
}, onDisposed: {
print("销毁")
})
}
打印结果:
订阅到:测试
完成
销毁
以上便是一个序列,从创建,到订阅,发送,接收,销毁的全过程。
那么接下来我们来撩开它滴裙子👗
一步一步来,
- 先来看
Observable<Any>.create
首先Cmd+点击Observable,进来了,找了一堆没找着.create,不急,看图
Observable.create
选择Create.Swift, 看到了啥,第一个就是ObservableType的create方法
小注: 有滴同学说我找的是
ObservableType与Observable关系Observable
的create
方法,你找的这个不是ObservableType
吗。
答: 方法查找流程。那么Observable
点进去你看
好滴,找到了create实现。
总结:我们看到我们所写的Observable<Any>.create
其实就是return了一个AnonymousObservable
对象的构造方法,也就是返回了一个AnonymousObservable
对象。这个对象中储存了我们发送的事件,需要回调的处理。
继续,本文件搜索AnonymousObservable,找到这个类
找到构造方法具体实现了
我们看到它啥也没干,只是把传给自己的匿名函数用成员变量保存了下来。OK,
Observable<Any>.create
干了啥我们知道了。继续-->
-
ob.subscribe
第二句代码ob.subscribe
老规矩 先点进去再说,CMD+点subscribe
ObservableType.subscribe
我再点:额。方法实现不给看了。 无妨,既然你都告诉我了是ObservableType
的subscribe(onNext:
balabala方法,那我自己找。还是看图:
图666: ObservableType的subscribe(onNext:...方法实现
好我们来到了重点了:
首先Disposable
放过不管
图中第一个绿框,创建了一个AnonymousObserver
订阅者对象。又是构造方法,又不给点进去?,没关系,我们自己查:
绿框框里看到啥,AnonymousObserver 的初始化构造方法时init(_ eventHandler: @escaping EventHandler),利用逃逸闭包写法,当逃逸闭包被当作函数参数初始化时,可以把闭包写开,这个gay位同学应该问题不大。
总结:
第一个绿框中干了啥?
一句话:创建了一个AnonymousObserver
对象,并且在创建时就保存了传进来的eventHandler的Block到自己的成员变量中。
ok,继续看图666中,AnonymousObserver
创建后,第二个绿框,return的时候调用了self.asObservable().subscribe(observer)
方法 (Disposables不用管,后续我会专门写一篇文章来介绍垃圾袋机制).
注意:注意:坑来了啊,self.asObservable().subscribe(observer)
,提问:想看subscribe的实现,那我们改找哪个类。
Observable? 错啦。仔细回忆下第一句代码,Observable<Any>.create
时做了什么,上面第一句代码总价加粗的字体:
因为第一句代码返回了一个AnonymousObservable
对象。所以此时self指的是AnonymousObservable
对象,而asObservable()
则是return了一个self,啥也没干,因此我们需要去找AnonymousObservable
的subscribe()方法
不信?看图,
self.asObservable().subscribe(observer)中,self指的是谁
走到这 ,恭喜,裙底的风光快显露了。
继续,找AnonymousObservable
的subscribe()方法,同样在Create.swift
文件中.
what the hell?为什么对象里没得subscribe()方法。 别急,子类找不着找谁?找爸爸。CMD+点Producer
Producer调用subscribe()方法图上看到,不管 if / else 都会创建SinkDisposer类,然后调用self.run方法.
注意: 别忘了,儿子
AnonymousObservable
重写了run方法,儿子没得方法才找到的爸爸Producer
,因此回到
AnonymousObservable
中,
终于被我看见裙底了。
AnonymousObservable对象,run方法
创建了AnonymousObservableSink对象,调用其run方法,
runrun干了啥?调用传参中parent的Block,传进来的parent是谁?
传进来是self,那self的
_subscribeHandler
是谁?ok 第一句代码create时我们保存的,也就是说,
总结:图666中第二个绿框(也就是self.asObservable().subscribe(observer)
)干了啥.
一: 保存了接收到事件时的回调.
二: 执行我们创建序列时的回调.
换句话说,此时接下来就走到了序列创建回调中。
序列创建回调
- 执行
observer.onNext("测试")
observer是谁呢,此处比较饶人,我补充了一片文章专门讲解,贴上链接RXSwift响应核心底层逻辑原理补充
那么接下来我们查找 AnonymousObserver
的 on()
方法
没找着on(Next)方法?找父类
ObserverBase
ObserverBase类以及on(_ event: Event<E>)方法
方法里使用了个
switch
,最后都调用了self.onCore(event)
方法,由于子类AnonymousObserver
重写了onCore方法所以回到子类调用(不信你看 大大的override写着),最终找到执行保存的_eventHandler
,参数为调用onNext时传递的参数,也就是我们写的字符串"测试",也就是我们创建订阅者时传进来的收到订阅回调。以及onCore方法
至此:从创建序列 -> 订阅序列 -> 发送信号 -> 信号接收整个流程我们已经分析完毕。(我都觉得自己啰嗦的不行,但是没办法,谁让是重点,老老实实吃透吧)。
最后流程总结:画图(改图为引用自Cooci老师)
响应流程核心原理完整流程
写这篇博客花了3个多小时,学习是枯燥的过程,但是坚持下来的时候是最爽的。
网友评论