Rx Swift
RxSwift 是 ReactiveX 成员之一,简单粗暴的理解一下RxSwift.
-
Event 事件
-
Observable 发布者
-
Subscribe 订阅
-
Observer 观察者
我们通过下面代码方便理解
- 单个事件
// 单个事件Observable:该Observable只能发出一个next事件 + 一个completed事件
//
// 1、调用Observable的类方法just就可以快捷创建一个单个事件observable,可以省略泛型,直接传你想发送的数据就行,会自动给你泛好
// 2、创建好、被监听后,该Observable就会自动发出事件
let justObservable = Observable.just(1)
// 等价于
let observable = Observable<Int>.create { observer in
observer.onNext(1)
observer.onCompleted()
return Disposables.create()
}
- 多个事件
// 多个事件Observable:该Observable能发出多个next事件 + 一个completed事件
//
// 1、调用Observable的类方法from或of就可以快捷创建一个多个事件observable,可以省略泛型,直接传你想发送的数据就行,会自动给你泛好
// 2、创建好、被监听后,该Observable就会自动发出事件
let fromObservable = Observable.from([1, 2, 3]) // 通过数组来生成多个next事件
let ofObservable = Observable.of(1, 2, 3) // 通过可变参数来生成多个next事件
// 等价于
let observable = Observable<Int>.create { observer in
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onCompleted()
return Disposables.create()
}
- 重复事件
// 重复N次Observable:给定一个重复次数N,该Observable就会重复发出同一个next事件N次 + 一个completed事件
let repeatElementObservable = Observable.repeatElement(1)
repeatElementObservable.take(5)
- 定时器 timer
// 定时器Observable:完全就是一个定时器,必须泛整型。延迟多长时间、每隔多长时间、在哪个线程,该Observable会像个定时器一样不断发出累加的整数
//
// 如果想取消定时器,其实不用取消定时器Observable,你只需要把监听行为给释放掉就可以了,这样的话定时器Observable还是存在的,它并不会发出completed事件或error事件
let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
-
Observer有两种类型:(它们都是一个泛型结构体
ObserverType
)-
AnyObserver(任意属性的观察者)
-
Binder(一般都是UI控件属性的观察者)
-
// 注意:类型为ObserverType
public struct AnyObserver<Element> : ObserverType {
...
}
// 注意:类型为ObserverType
public struct Binder<Element>: ObserverType {
...
}
需要注意的是Observer想要监听的数据的数据类型就是泛型的这个Element,如果它跟Observable和Event那里的泛型Element不一样,我们就得先通过map等函数把数据类型给搞一样。
- AnyObserver做相应的处理
// 1、怎么创建一个anyObeserver?
//
// 调用AnyObserver的init方法就可以创建一个anyObserver,假设这个anyObserver想要监听的数据的数据类型为Int
//
// init方法的入参是一个闭包,这个闭包的入参是一个event——这个event就是将来被观察的Observable所发出的事件,这个闭包的执行体就是AnyObserver要做的处理
let anyObserver = AnyObserver<Int>.init { event in
// 2、anyObserver怎么做出相应的处理?
// 在这个闭包的执行体里做相应的处理即可
switch event {
case .next:
print("next:\(event.element)")
case .error:
print("error:\(event.error)")
case .completed:
print("completed")
}
}
- Binder做相应的处理
// 1、怎么创建一个Binder?
//
// 调用Binder的init方法就可以创建一个binder,假设这个binder想要监听的数据的数据类型为String(假设我们想监听字符串数据,把监听到的字符串数据设置到一个label上显示)
//
// init方法的第一个入参是指你要把监听到的数据设置给谁来使用,通常是一个UI控件
// init方法的第二个入参是一个闭包,这个闭包的第一个入参就是前面的那个UI控件,第二个入参就是监听到的字符串数据,这个闭包的执行体就是binder要做的处理
let binder = Binder<String>.init(label) { label, element in
// 2、binder怎么做出相应的处理?
// 在这个闭包的执行体里做相应的处理即可
label.text = element
}
Observer监听Observable,以及监听行为的释放
- Observable Subscribe AnyObserver
let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
let anyObserver = AnyObserver<Int>.init { event in
switch event {
case .next:
print("next:\(event.element)") // 会打印:0、1、2、3、...
case .error:
print("error:\(event.error)")
case .completed:
print("completed")
}
}
timerObservable.subscribe(anyObserver)
- Observable Subscribe Binder
// 界面上搞一个label
@IBOutlet weak var label: UILabel!
let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
let binder = Binder<String>.init(label) { label, element in
label.text = element
}
// binder监听timerObservable
// 但是timerObservable发出的事件挂的数据是Int类型
// 而binder监听的确实String类型
// 所以得把timerObservable发出的事件挂的Int数据通过map函数转换成String数据
// 就这么简单
timerObservable
.map { element in
return "数字是:\(element)"
}
.subscribe(binder)
// Binder还有一个专门的bindTo方法用来监听Observable,不过跟subscribe方法是等价的
timerObservable
.map { element in
return "数字是:\(element)"
}
.bind(to: binder)
- 广义上的观察者
let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
// 方式1
timerObservable
.subscribe { event in
switch event {
case .next:
print("next:\(event.element)") // 会打印:0、1、2、3、...
case .error:
print("error:\(event.error)")
case .completed:
print("completed")
}
}
// 方式2
timerObservable
.subscribe(onNext: { element in
print("next:\(element)") // 会打印:0、1、2、3、...
}, onError: { error in
print("error:\(error)")
}, onCompleted: {
print("completed")
})
subscribe 函数有一个返回值 Disposable
- disposable
立即释放监听行为
(实际开发中使用较少)
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
let anyObserver = AnyObserver<Int>.init { event in
switch event {
case .next:
print("next:\(event.element)")
case .error:
print("error:\(event.error)")
case .completed:
print("completed")
}
}
let disposable = timerObservable.subscribe(anyObserver)
// 立即释放监听行为——即接收完释放之前的一波数据后立即释放,类似于release
disposable.dispose()
}
}
- disposable
自动释放监听行为
(实际开发中使用较多)
class ViewController: UIViewController {
// 类似于autoreleasepool
//
// 它会把所有的监听行为都放进去,等到它即将销毁时再对它里面所有的监听行为都调用一次dispose方法
// 现在bag属性的生命周期是跟当前viewController一样的
let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
let anyObserver = AnyObserver<Int>.init { event in
switch event {
case .next:
print("next:\(event.element)")
case .error:
print("error:\(event.error)")
case .completed:
print("completed")
}
}
timerObservable.subscribe(anyObserver).disposed(by: bag)
}
}
-
用手
释放监听行为
class ViewController: UIViewController {
// 定义一个属性
var disposable: Disposable?
override func viewDidLoad() {
super.viewDidLoad()
let timerObservable = Observable<Int>.timer(.seconds(3), period: .seconds(1), scheduler: MainScheduler.instance)
let anyObserver = AnyObserver<Int>.init { event in
switch event {
case .next:
print("next:\(event.element)")
case .error:
print("error:\(event.error)")
case .completed:
print("completed")
}
}
// 把监听行为记录下来
disposable = timerObservable.subscribe(anyObserver)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
// 在合适的时机手动释放监听行为
disposable?.dispose()
}
}
Subjects
-
PublishSubject
- publishSubject在充当Observable发出事件,也能充当Observer
class ViewController: UIViewController {
let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let publishSubject = PublishSubject<Int>.init()
// 这里publishSubject在充当Observer的角色,帮Observable发出事件
// 还记得之前创建Observable时,Observable是怎么发出事件的吗?就是给Observer发送onNext消息发出的,onNext本来就是Observer的方法,所以这里就体现了publishSubject在充当Observer的角色
publishSubject.onNext(1)
publishSubject.onNext(2)
publishSubject.onNext(3)
// 这里publishSubject在充当Observable的角色,只会向观察者发送观察者监听它之后的事件,不会向观察者发送观察者监听它之前的事件
publishSubject.subscribe { event in
print(event) // 4、5、6
}.disposed(by: bag)
publishSubject.onNext(4)
publishSubject.onNext(5)
publishSubject.onNext(6)
}
}
-
BehaviorSubject
- behaviorSubject在充当Observable发出事件,也能充当Observer
class ViewController: UIViewController {
let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let behaviorSubject = BehaviorSubject<Int>(value: 1)
// 这里behaviorSubject在充当Observer的角色,帮Observable发出事件
behaviorSubject.onNext(2)
behaviorSubject.onNext(3)
// 这里behaviorSubject在充当Observable的角色,会向观察者发送观察者监听它之前的最后一个事件 + 观察者监听它之后的事件
behaviorSubject.subscribe { event in
print(event) // 3、4、5、6
}.disposed(by: bag)
behaviorSubject.onNext(4)
behaviorSubject.onNext(5)
behaviorSubject.onNext(6)
}
}
-
ReplaySubject
- replaySubject在充当Observable发出事件,也能充当Observer, 可控制缓存数量
class ViewController: UIViewController {
let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let replaySubject = ReplaySubject<Int>.create(bufferSize: 2) // 假设要缓存两个事件
// 这里replaySubject在充当Observer的角色,帮Observable发出事件
replaySubject.onNext(1)
replaySubject.onNext(2)
replaySubject.onNext(3)
// 这里replaySubject在充当Observable的角色,会向观察者发送观察者监听它之前缓存的N个事件 + 观察者监听它之后的事件
replaySubject.subscribe { event in
print(event) // 2、3、4、5、6。缓存的是最后两个事件,因为是序列,所以会按顺序把事件发出来
}.disposed(by: bag)
replaySubject.onNext(4)
replaySubject.onNext(5)
replaySubject.onNext(6)
}
}
-
BehaviorRelay
- behaviorRelay在充当Observable发出事件,也能充当Observer
class ViewController: UIViewController {
let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let behaviorRelay = BehaviorRelay<Int>.init(value: 1)
// 这里behaviorRelay在充当Observer的角色,帮Observable发出事件
behaviorRelay.accept(2)
behaviorRelay.accept(3)
// 这里behaviorRelay在充当Observable的角色,会向观察者发送观察者监听它之前的最后一个事件 + 观察者监听它之后的事件
behaviorRelay.subscribe { event in
print(event) // 3、4、5、6
}.disposed(by: bag)
behaviorRelay.accept(4)
behaviorRelay.accept(5)
behaviorRelay.accept(6)
}
}
实际开发中的用法示例
- button点击事件
//MARK: - RxSwift应用-button响应
func setupButton() {
// 传统UI事件
self.button.addTarget(self, action: #selector(didClickButton), for: .touchUpInside)
// 这样的操作 - 不行啊!代码逻辑与事件逻辑分层
self.button.rx.tap
.subscribe(onNext: { [weak self] in
print("点了,你的小鸡鸡")
self?.view.backgroundColor = UIColor.orange
})
.disposed(by: disposeBag)
}
- textfiled文本响应
//MARK: - RxSwift应用-textfiled
func setupTextFiled() {
// 我们如果要对输入的文本进行操作 - 比如输入的的内容 然后我们获取里面的偶数
// self.textFiled.delegate = self
// 感觉是不是特别恶心
// 下面我们来看看Rx
self.textFiled.rx.text.orEmpty.changed.subscribe(onNext: { (text) in
print("监听到了 - \(text)")
}).disposed(by: disposeBag)
self.textFiled.rx.text.bind(to: self.button.rx.title()).disposed(by: disposeBag)
}
- scrollView效果
//MARK: - RxSwift应用-scrollView
func setupScrollerView() {
scrollView.rx.contentOffset.subscribe(onNext: { [weak self] (content) in
self?.view.backgroundColor = UIColor.init(red: content.y/255.0*0.8, green: content.y/255.0*0.3, blue: content.y/255.0*0.6, alpha: 1);
print(content.y)
}).disposed(by: disposeBag)
}
- KVO
//MARK: - RxSwift应用-KVO
func setupKVO() {
// 系统KVO 还是比较麻烦的
// person.addObserver(self, forKeyPath: "name", options: .new, context: nil)
person.rx.observeWeakly(String.self, "name").subscribe(onNext: { (change) in
print(change ?? "helloword")
}).disposed(by: disposeBag)
}
- notification
//MARK: - 通知
func setupNotification(){
NotificationCenter.default.rx
.notification(UIResponder.keyboardWillShowNotification)
.subscribe { (event) in
print(event)
}.disposed(by: disposeBag)
}
- gesture
//MARK: - 手势
func setupGestureRecognizer(){
let tap = UITapGestureRecognizer()
self.label.addGestureRecognizer(tap)
self.label.isUserInteractionEnabled = true
tap.rx.event.subscribe { (event) in
print("点了label")
}.disposed(by: disposeBag)
}
- network request
//MARK: - RxSwift应用-网络请求
func setupNextwork() {
let url = URL(string: "https://www.baidu.com")
URLSession.shared.rx.response(request: URLRequest(url: url!))
.subscribe(onNext: { (response, data) in
print("response ==== \(response)")
print("data ===== \(data)")
}, onError: { (error) in
print("error ===== \(error)")
}).disposed(by: disposeBag)
}
- timer
//MARK: - RxSwift应用-timer定时器
func setupTimer() {
timer = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
timer.subscribe(onNext: { (num) in
print("hello word \(num)")
}).disposed(by: disposeBag)
}
RxSwift实现的timer免去了我们计时器的一些不必要的麻烦
runloop影响
销毁问题
线程问题
666 哈哈哈哈哈哈
网友评论