Rx
Rx是ReactiveX的縮寫,簡單來說就是基于異步事件序列的響應(yīng)式編程。
RxSiwft:他只是基于Swift語言的Rx標(biāo)準(zhǔn)實(shí)現(xiàn)接口庫,所以RxSwift里不包含任何Cocoa或者UI方面的類。
RxCocoa:是基于RxSwift針對(duì)于iOS開發(fā)的一個(gè)庫,他通過Extension的方法給原生的比如UI控件添加了Rx的特性,使得我們更容易訂閱和響應(yīng)這些控件。
Obsevable
·Observable<T>這個(gè)類就是Rx框架的基礎(chǔ),我們可以稱它為可觀察序列。它的作用就是可以異步的產(chǎn)生一系列的事件,即一個(gè)Observable<T>對(duì)象會(huì)隨著時(shí)間推移不定期的發(fā)出event(element: T)這樣一個(gè)東西。
·而且這些事件還可以攜帶數(shù)據(jù),他的泛型<T>就是用來指定這個(gè)事件攜帶的數(shù)據(jù)的類型。
·有了可觀察序列,我們還需要有一個(gè)Observer(訂閱者)來訂閱它這樣這個(gè)訂閱者才能收到Observable<T>不是發(fā)出的事件
可以看到事件就是一個(gè)枚舉,也就是說一個(gè)Observable是可以發(fā)出3種不同類型的事件(next,error, completed)
Observable的創(chuàng)建方法
1.just()該方法通過傳入一個(gè)默認(rèn)值來初始化
let observable = Observable<Int>.just(5)
2.of()該方法可以接受可變數(shù)量的參數(shù)(必須要是同類型的)
let observable = Observable.of("A", "B","C")
3.from()該方法需要一個(gè)數(shù)組參數(shù)
let observable = Observable.from(["A", "B","C"])
4.empty()該方法創(chuàng)建一個(gè)空內(nèi)容的Observable
let observable = Observable<Int>
5.never()該方法創(chuàng)建一個(gè)永遠(yuǎn)不會(huì)發(fā)出事件(也不會(huì)終止)的Observable序列
let observable = Observable<Int>.never()
6.error()該方法創(chuàng)建一個(gè)不做任何操作,而是直接發(fā)送一個(gè)錯(cuò)誤的Observable序列
enum MyError: Error {
case A
case B
}
let observable = Observable<int>.error(MyError.A)
7.range()該方法通過指定起始和結(jié)束數(shù)值,創(chuàng)建一個(gè)以這個(gè)范圍內(nèi)所有值作為初始值的Observable序列
let observable = Observable.range(start: 1, count: 5)
let observable = Observable.of(1, 2, 3, 4, 5)
8.repeatElement()該方法創(chuàng)建一個(gè)可以無限發(fā)出給定元素的Event的Observable序列(永不終止)
let observable = Observable.repeatElement(1)
9.generate()該方法創(chuàng)建一個(gè)只有當(dāng)提供的所有的判斷條件都為真的時(shí)候,才會(huì)給出動(dòng)作的Observable序列
let obsevable = Observable.generate(
initialState: 0,
condition: { $0 <= 10 },
iterate: { $0 + 2 }
)
let observable = Observable.of(0, 2, 4, 6, 8, 10)
10.create()該方法接受一個(gè)block形式的參數(shù),任務(wù)是對(duì)每一個(gè)過來的訂閱進(jìn)行處理
//這個(gè)block有一個(gè)回調(diào)參數(shù)observer就是訂閱這個(gè)Observable對(duì)象的訂閱者
//當(dāng)一個(gè)訂閱者訂閱這個(gè)Observable對(duì)象的時(shí)候,就會(huì)講經(jīng)樂者作為參數(shù)傳入這個(gè)block來執(zhí)行一些內(nèi)容
let observable = Observable<String>.create{ observer in
observer.onNext("Hello")
observer.onCompleted()
//因?yàn)橐粋€(gè)訂閱行為會(huì)有一個(gè)Disposable類型的返回值,所以在結(jié)尾一定要return一個(gè)Disposable
return Disposables.create()
}
observable.subscribe {
print($0)
}
11.defferred()該方法相當(dāng)于創(chuàng)建一個(gè)Observable工廠,通過傳入一個(gè)block來執(zhí)行延遲Observable序列創(chuàng)建的行為,而這個(gè)block里就是真正的實(shí)例化序列對(duì)象的地方。
var isOdd = true
let factory: Observable<Int> = Observable.deferred {
isOdd = !isOdd
if isOdd {
return Observable.of(1, 3, 5, 7)
} else {
return Observable.of(2, 4, 6, 8)
}
}
factory.subscribe { event in
print("\(isOdd)", event)
}
factory.subscribe { event in
print("\(isOdd)", event)
}
12.interval()該方法創(chuàng)建的Observable序列每隔一段設(shè)定的時(shí)間,就發(fā)出一個(gè)索引數(shù)的元素。而且他會(huì)一直發(fā)送下去。
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable.subscribe { event in
print(event)
}
13.timer()
(1).這個(gè)方法有兩種用法,一種是創(chuàng)建的Observable序列在經(jīng)過設(shè)定的一段時(shí)間后,產(chǎn)生唯一的一個(gè)元素
// 5秒鐘后發(fā)出唯一的一個(gè)元素0
let observable = Observable<int>.timer(5, scheduler: MainScheduler.instance)
observable.subscribe { event in
print(event)
}
(2).另一種是創(chuàng)建的Observable序列在經(jīng)過設(shè)定的一段時(shí)間后,每隔一段時(shí)間產(chǎn)生一個(gè)元素
//延時(shí)5秒后,每隔1秒發(fā)出一個(gè)元素
let observable = Observable<Int>.timer(5, period: 1, scheduler:MainScheduler.instance)
observable.subscribe { event in
print(event)
}
訂閱Observable
用法一:
我們使用subscribe()訂閱了一個(gè)Observable對(duì)象,該方法的block的回調(diào)參數(shù)就是被發(fā)出的event事件
如果想要獲取到這個(gè)事件中的數(shù)據(jù),可以通過event,element得到
let observable = Observable.of(0, 2, 4, 6, 8, 10)
observable.subscribe { event in
print(event.element)
}
用法二:
RxSwift還提供了另一個(gè)subscribe方法。他可以吧event分類
let observable = Observable.of(0, 2, 4, 6, 8, 10)
observable.subscribe(onNext: { element in
print(element)
}, onError: { error in
print(error)
}, onCompleted: {
print("comepleted")
}, onDisposed: {
print("disposed")
})
監(jiān)聽事件的生命周期
doOn監(jiān)聽事件的生命周期
let observable = Observable.of(0, 2, 4, 6, 8, 10)
observable
doOn(onNext: { element in
print("Intercepted Next:", element)
}, onError: { error in
print("Intercepted Error:", error)
}, onCompleted: {
print("Intercepted comepleted")
}, onDisposed: {
print("Intercepted disposed")
})
.subscribe(onNext: { element in
print(element)
}, onError: { error in
print(error)
}, onCompleted: {
print("comepleted")
}, onDisposed: {
print("disposed")
})
Observable的銷毀(Dispose)
dispose()該方法可以手動(dòng)取消一個(gè)訂閱行為
let observable = Observable.of(0, 2, 4, 6, 8, 10)
let subscription = observable.subscribe { event in
print(event)
}
subscription.dispose()
除了dispose()方法之外,我們更經(jīng)常用到的是一個(gè)叫DisposeBag的對(duì)象來管理多個(gè)訂閱行為的銷毀,他會(huì)在自己快要dealloc的時(shí)候,對(duì)它里面的所有訂閱行為都屌用dispose()
let disposeBag = DisposeBag()
let observable1 = Observable.of("A", "B", "C")
observable1.subscribe { event in
print(event)
}.disposed(by: disposeBag)
let observable2 = Observable.of(1, 2, 3)
observable2.subscribe { event in
print(event)
}.disposed(by: disposeBag)
觀察者(Observer)
觀察者的作用就是監(jiān)聽事件,然后對(duì)這個(gè)事件作出相應(yīng)。
1.在subscribe方法中創(chuàng)建
創(chuàng)建觀察者最直接的方法就是在Observable的subscribe方法后面描述當(dāng)事件發(fā)生時(shí),需要如何做出響應(yīng)。
2.在bind方法中創(chuàng)建
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
let disposeBag = DisposeBag()
override func viewDidLoad() {
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable
.map { "當(dāng)前縮陰術(shù):\($0)" }
.bind { [weak self](text) in
self?.label.text = text
}
.disposed(by: disposeBag)
}
}
使用AnyObserver創(chuàng)建觀察者
1.配合subscribe方法使用
let observer: AnyObserver<String> = AnyObserver { (event) in
switch event {
case .next(let data):
print(data)
case .error(let error):
print(error)
case .completed:
print("completed")
}
}
let observable = Observable.of("A", "B", "C")
observable.subscribe(observer)
2.配合bindTo使用
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
let disposeBag = DisposeBag()
override func viewDidLoad() {
let observer: AnyObserver<String> = AnyObserver { [weak self] (event) in
switch event {
case .next(let text):
self?.label.text = text
default:
break
}
}
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable
.map { "當(dāng)前縮陰術(shù):\($0)" }
.bind(to: observer)
.disposed(by: disposeBag)
}
}
使用Binder創(chuàng)建觀察者
1.相較于AnyObserver的大而全,Binder更專注于特定的場(chǎng)景。Binder主要有以下兩個(gè)特征:
·不會(huì)處理錯(cuò)誤事件
·確保綁定都是在給定Scheduler上執(zhí)行(默認(rèn)MainScheduler)
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
let disposeBag = DisposeBag()
override func viewDidLoad() {
let observer: Binder<String> = Binder(label) { (view, text) in
view.text = text
}
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable
.map { "當(dāng)前縮陰術(shù):\($0)" }
.bind(to: observer)
.disposed(by: disposeBag)
}
}
自定義可綁定屬性
方式一:通過對(duì)UI類進(jìn)行擴(kuò)展
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
let disposeBag = DisposeBag()
override func viewDidLoad() {
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable
.map { "當(dāng)前縮陰術(shù):\($0)" }
.bind(to: label.fontSize)
.disposed(by: disposeBag)
}
}
extension UILabel {
public var fontSize: Binder<CGFloat> {
return Binder(self) { label, fontSize in
label.font = UIFont.systemFont(ofSize: fontSize)
}
}
}
方式二:通過對(duì)Reactive類進(jìn)行擴(kuò)展
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
let disposeBag = DisposeBag()
override func viewDidLoad() {
let observable = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
observable
.map { "當(dāng)前縮陰術(shù):\($0)" }
.bind(to: label.rx.fontSize)
.disposed(by: disposeBag)
}
}
extension Reactive where Base: UILabel {
public var fontSize: Binder<CGFloat> {
return Binder(self.base) { label, fontSize in
label.font = UIFont.systemFont(ofSize: fontSize)
}
}
}
Subjects
Subjects既是訂閱者,也是Observable
一共有四種Subjects,分別是PublishSubject,BehaviorSubject,ReplaySubject,Variable.她們之間最大的區(qū)別只是在于:當(dāng)一個(gè)新的訂閱者剛好訂閱它的時(shí)候,能不能收到Subject以前發(fā)出過的舊事件,如果能的話又能收到多少個(gè)。
PublishSubject
- PublishSubject不需要初始值就能創(chuàng)建
- PublishSubject的訂閱者從他們呢開始訂閱的時(shí)間點(diǎn)起,可以收到訂閱后Subject發(fā)出的新事件,而不會(huì)收到他們呢在訂閱前已發(fā)出的事件
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
subject.onNext("111")
subject.subscribe(onNext: { string in
print("第1次訂閱:", string)
}, onCompleted: {
print("第1次訂閱:onCompleted")
}).disposed(by: disposeBag)
subject.onNext("222")
subject.subscribe(onNext: { string in
print("第2次訂閱:", string)
}, onCompleted: {
print("第2次訂閱:onCompleted")
}).disposed(by: disposeBag)
subject.onNext("333")
subject.onCompleted()
subject.onNext("444")
subject.subscribe(onNext: { string in
print("第3次訂閱:", string)
}, onCompleted: {
print("第3次訂閱:onCompleted")
}).disposed(by: disposeBag)
BehaviorSubject
1.需要一個(gè)默認(rèn)初始值來創(chuàng)建
2.當(dāng)一個(gè)訂閱者來訂閱它的時(shí)候,這個(gè)訂閱者會(huì)立即收到BehaviorSubject上一個(gè)發(fā)出的事件。之后就跟正常的情況一樣,他也會(huì)接收到BehaviorSubject之后發(fā)出的新的事件
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "111")
subject.subscrbe { event in
print("第1次訂閱:", event)
}.disposed(by: disposeBag)
subject.onNext("222")
subject.onError(NSError(domain: "local", code: 0, userInfo:nil))
subject.subscribe { event in
print("第2次訂閱:", event)
}.disposed(by: disposeBag)
ReplaySubject
ReplaySubject在創(chuàng)建時(shí)候需要設(shè)置一個(gè)bufferSize,表示他對(duì)于他發(fā)送過的事件的緩存?zhèn)€數(shù)。
如果一個(gè)subscriber訂閱已經(jīng)結(jié)束的ReplaySubject,除了會(huì)收到緩存的。next的事件外,還會(huì)收到那個(gè)終結(jié)的.error或者.complete的事件。
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 2)
subject.onNext("111")
subject.onNext("222")
subject.onNext("333")
subject.subscribe { event in
print("第1次訂閱:", event)
}.disposed(by: disposeBag)
subject.onNext("444")
subject.subscribe { event in
print("第2次訂閱:", event)
}.disposed(by: disposeBag)
subject.onCompleted()
subject.subscribe { event in
print("第3次訂閱:", event)
}.disposed(by: disposeBag)
Variable
Variable其實(shí)就是對(duì)BehaviorSubject的封裝,所以他也必須要通過一個(gè)默認(rèn)的初始值進(jìn)行創(chuàng)建
不同的是,Variable還會(huì)把當(dāng)前發(fā)出的值保存為自己的狀態(tài)。同時(shí)他會(huì)在銷毀時(shí)自動(dòng)發(fā)送.complete的事件,不需要也不能手動(dòng)給Variables發(fā)送completed或者error事件來結(jié)束它
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let disposeBag = DisposeBag()
let variable = Variable("111")
variable.value = "222"
variable.asObservable().subscribe {
print("第1次訂閱:", $0)
}.disposed(by: disposeBag)
variable.value = "333"
variable.asObservable().subscribe {
print("第2次訂閱:", $0)
}.disposed(by: disposeBag)
variable.value = "444"
}
}
操作符
變換操作指的是對(duì)原始的Observable序列進(jìn)行一些轉(zhuǎn)換。
buffer 方法作用是緩沖組合,第一個(gè)參數(shù)是緩沖時(shí)間,第二個(gè)參數(shù)是緩沖個(gè)數(shù),第三個(gè)參數(shù)是線程
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let subject = PublishSubject<String>()
//沒緩存3個(gè)元素則組合起來一起發(fā)出
//如果1秒鐘內(nèi)不夠3個(gè)也會(huì)發(fā)出(有幾個(gè)發(fā)幾個(gè),一個(gè)都沒有發(fā)空數(shù)組[])
subject
.buffer(timeSpan: 1, count: 3, scheduler:MainScheduler.instance)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject.onNext("a")
subject.onNext("b")
subject.onNext("c")
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
}
}
window 操作符和buffer十分相識(shí),不過buffer是周期性的將緩存的元素集合發(fā)送出去,而window周期性的將元素集合以O(shè)bservable的形態(tài)發(fā)送出來。同時(shí)buffer要等到元素搜集完畢后,才會(huì)發(fā)出元素序列,而window可以實(shí)時(shí)發(fā)出元素序列
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let subject = PublishSubject<String>()
//每3個(gè)元素作為一個(gè)子Observable發(fā)出
subject
.window(timeSpan: 1, count: 3, scheduler:MainScheduler.instance)
.subscribe(onNext: { [weak self] in
print("subscribe: \($0)")
$0.asObservable()
.subscribe(onNext: { print($0) })
.disposed(by: self!.disposeBag)
})
.disposed(by: disposeBag)
subject.onNext("a")
subject.onNext("b")
subject.onNext("c")
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
}
}
map 該操作符通過傳入一個(gè)函數(shù)閉包原來的Observable序列轉(zhuǎn)變?yōu)橐粋€(gè)新的Observable序列
let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
.map { $0 * 10 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
filter 該操作符就是用來過濾掉某些不符合要求的事件
let disposeBag = DisposeBag()
Observable.of(2, 30, 22, 5, 60, 3, 40, 9)
.filter {
$0 > 10
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
distinctUntilChanged 該操作符永雨過濾掉重復(fù)的事件
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 1, 1, 4)
. distinctUntilChanged()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
single 限制只發(fā)送一次事件,或者滿足條件的第一個(gè)事件,如果存在多個(gè)事件或者沒有事件都會(huì)發(fā)出一個(gè)error事件。如果只有一個(gè)事件,則不會(huì)發(fā)出error事件
elementAt 該方法實(shí)現(xiàn)只處理在指定位置的事件
ignoreElements 該操作符可以忽略掉所有的元素,只發(fā)出error或completed事件
take 該方法僅發(fā)送Observable序列中的前n個(gè)事件,在滿足數(shù)量之后會(huì)自動(dòng).completed
takeLast 該方法實(shí)現(xiàn)僅發(fā)送Observable序列中的后n個(gè)事件
skip 該方法用于跳過Observable序列發(fā)出的前n個(gè)事件
amb 當(dāng)傳入多個(gè)Observable到amb操作符時(shí),它將取第一個(gè)發(fā)出元素或產(chǎn)生事件的 Observable,然后只發(fā)出它的元素。并忽略掉其他的 Observables。
takeWhile 該方法依次判斷 Observable 序列的每一個(gè)值是否滿足給定的條件。 當(dāng)?shù)谝粋€(gè)不滿足條件的值出現(xiàn)時(shí),它便自動(dòng)完成。
takeUntil 除了訂閱源Observable外,通過 takeUntil 方法我們還可以監(jiān)視另外一個(gè) Observable, 即 notifier。如果 notifier 發(fā)出值或 complete 通知,那么源 Observable 便自動(dòng)完成,停止發(fā)送事件。
skipWhile 該方法用于跳過前面所有滿足條件的事件。一旦遇到不滿足條件的事件,之后就不會(huì)再跳過了。
skipUntil 同上面的 takeUntil 一樣,skipUntil 除了訂閱源 Observable 外,通過 skipUntil方法我們還可以監(jiān)視另外一個(gè) Observable, 即 notifier。與 takeUntil 相反的是。源 Observable 序列事件默認(rèn)會(huì)一直跳過,直到 notifier 發(fā)出值或 complete 通知。
結(jié)合操作
結(jié)合操作(或者稱合并操作)指的是將多個(gè) Observable 序列進(jìn)行組合,拼裝成一個(gè)新的 Observable 序列。
startWith 該方法會(huì)在 Observable 序列開始之前插入一些事件元素。即發(fā)出事件消息之前,會(huì)先發(fā)出這些預(yù)先插入的事件消息。
merge 該方法可以將多個(gè)(兩個(gè)或兩個(gè)以上的)Observable 序列合并成一個(gè) Observable序列。
zip 該方法可以將多個(gè)(兩個(gè)或兩個(gè)以上的)Observable 序列壓縮成一個(gè) Observable 序列。而且它會(huì)等到每個(gè) Observable 事件一一對(duì)應(yīng)地湊齊之后再合并。
combineLatest 該方法同樣是將多個(gè)(兩個(gè)或兩個(gè)以上的)Observable 序列元素進(jìn)行合并。但與 zip 不同的是,每當(dāng)任意一個(gè) Observable 有新的事件發(fā)出時(shí),它會(huì)將每個(gè) Observable 序列的最新的一個(gè)事件元素進(jìn)行合并。
withLatestFrom 該方法將兩個(gè) Observable 序列合并為一個(gè)。每當(dāng) self 隊(duì)列發(fā)射一個(gè)元素時(shí),便從第二個(gè)序列中取出最新的一個(gè)值。
switchLatest switchLatest 有點(diǎn)像其他語言的switch 方法,可以對(duì)事件流進(jìn)行轉(zhuǎn)換。比如本來監(jiān)聽的 subject1,我可以通過更改 variable 里面的 value 更換事件源。變成監(jiān)聽 subject2。
算數(shù),以及聚合操作
toArray 該操作符先把一個(gè)序列轉(zhuǎn)成一個(gè)數(shù)組,并作為一個(gè)單一的事件發(fā)送,然后結(jié)束。
reduce 接受一個(gè)初始值,和一個(gè)操作符號(hào)。將給定的初始值,與序列里的每個(gè)值進(jìn)行累計(jì)運(yùn)算。得到一個(gè)最終結(jié)果,并將其作為單個(gè)值發(fā)送出去。
concat 會(huì)把多個(gè) Observable 序列合并(串聯(lián))為一個(gè) Observable 序列。并且只有當(dāng)前面一個(gè) Observable 序列發(fā)出了 completed 事件,才會(huì)開始發(fā)送下一個(gè) Observable 序列事件。
連接操作
可連接的序列
1.可連接的序列和一般序列不同在于:有訂閱時(shí)不會(huì)立刻開始發(fā)送事件消息,只有當(dāng)調(diào)用connect()之后才會(huì)開始發(fā)送值
2.可連接的序列可以讓所有的訂閱者訂閱后,才開始發(fā)出事件消息,從而保證我們想要的所有訂閱者都能接收到事件消息
publish 方法會(huì)將一個(gè)正常的序列轉(zhuǎn)換成一個(gè)可連接的序列。同時(shí)該序列不會(huì)立刻發(fā)送事件,只有在調(diào)用 connect 之后才會(huì)開始。
replay 與 publish 不同在于:新的訂閱者還能接收到訂閱之前的事件消息(數(shù)量由設(shè)置的 bufferSize 決定)
multicast 方法還可以傳入一個(gè) Subject,每當(dāng)序列發(fā)送事件時(shí)都會(huì)觸發(fā)這個(gè) Subject 的發(fā)送。
delay 該操作符會(huì)將 Observable 的所有元素都先拖延一段設(shè)定好的時(shí)間,然后才將它們發(fā)送出來。
delaySubscription 使用該操作符可以進(jìn)行延時(shí)訂閱。即經(jīng)過所設(shè)定的時(shí)間后,才對(duì) Observable 進(jìn)行訂閱操作。
materialize 該操作符可以將序列產(chǎn)生的事件,轉(zhuǎn)換成元素。通常一個(gè)有限的 Observable 將產(chǎn)生零個(gè)或者多個(gè) onNext 事件,最后產(chǎn)生一個(gè) onCompleted 或者onError事件。而 materialize 操作符會(huì)將 Observable 產(chǎn)生的這些事件全部轉(zhuǎn)換成元素,然后發(fā)送出來。
dematerialize 該操作符的作用和 materialize 正好相反,它可以將 materialize 轉(zhuǎn)換后的元素還原。
timeout 使用該操作符可以設(shè)置一個(gè)超時(shí)時(shí)間。如果源 Observable 在規(guī)定時(shí)間內(nèi)沒有發(fā)任何出元素,就產(chǎn)生一個(gè)超時(shí)的 error 事件。
using 使用 using 操作符創(chuàng)建 Observable 時(shí),同時(shí)會(huì)創(chuàng)建一個(gè)可被清除的資源,一旦 Observable終止了,那么這個(gè)資源就會(huì)被清除掉了。
錯(cuò)誤處理操作
錯(cuò)誤處理操作符可以用來幫助我們對(duì) Observable 發(fā)出的 error 事件做出響應(yīng),或者從錯(cuò)誤中恢復(fù)。
catchErrorJustReturn 當(dāng)遇到 error 事件的時(shí)候,就返回指定的值,然后結(jié)束。
catchError 該方法可以捕獲 error,并對(duì)其進(jìn)行處理。
retry 使用該方法當(dāng)遇到錯(cuò)誤的時(shí)候,會(huì)重新訂閱該序列。比如遇到網(wǎng)絡(luò)請(qǐng)求失敗時(shí),可以進(jìn)行重新連接。retry() 方法可以傳入數(shù)字表示重試次數(shù)。不傳的話只會(huì)重試一次。
調(diào)試操作
debug 我們可以將 debug 調(diào)試操作符添加到一個(gè)鏈?zhǔn)讲襟E當(dāng)中,這樣系統(tǒng)就能將所有的訂閱者、事件、和處理等詳細(xì)信息打印出來,方便我們開發(fā)調(diào)試。
RxSwift.Resources.total 通過將 RxSwift.Resources.total 打印出來,我們可以查看當(dāng)前 RxSwift 申請(qǐng)的所有資源數(shù)量。這個(gè)在檢查內(nèi)存泄露的時(shí)候非常有用。
除了Observable,RxSwift 還為我們提供了一些特征序列(Traits):Single、Completable、Maybe、Driver、ControlEvent。
區(qū)別:
1.Observable 是能夠用于任何上下文環(huán)境的通用序列。
2.而 Traits 可以幫助我們更準(zhǔn)確的描述序列。同時(shí)它們還為我們提供上下文含義、語法糖,讓我們能夠用更加優(yōu)雅的方式書寫代碼。
Single 是 Observable 的另外一個(gè)版本。但它不像 Observable 可以發(fā)出多個(gè)元素,它要么只能發(fā)出一個(gè)元素,要么產(chǎn)生一個(gè) error 事件。
Single 比較常見的例子就是執(zhí)行 HTTP 請(qǐng)求,然后返回一個(gè)應(yīng)答或錯(cuò)誤。不過我們也可以用 Single 來描述任何只有一個(gè)元素的序列。
為方便使用,RxSwift 還為 Single 訂閱提供了一個(gè)枚舉(SingleEvent):
.success:里面包含該Single的一個(gè)元素值
.error:用于包含錯(cuò)誤
我們可以通過調(diào)用 Observable 序列的.asSingle()方法,將它轉(zhuǎn)換為 Single。
Completable 是 Observable 的另外一個(gè)版本。不像 Observable 可以發(fā)出多個(gè)元素,它要么只能產(chǎn)生一個(gè) completed 事件,要么產(chǎn)生一個(gè) error 事件。
為方便使用,RxSwift 為 Completable 訂閱提供了一個(gè)枚舉(CompletableEvent):
.completed:用于產(chǎn)生完成事件
.error:用于產(chǎn)生一個(gè)錯(cuò)誤
Maybe 同樣是 Observable 的另外一個(gè)版本。它介于 Single 和 Completable 之間,它要么只能發(fā)出一個(gè)元素,要么產(chǎn)生一個(gè) completed 事件,要么產(chǎn)生一個(gè) error 事件。
我們可以通過調(diào)用 Observable 序列的 .asMaybe()方法,將它轉(zhuǎn)換為 Maybe。
Driver
1.可以說是最復(fù)雜的 trait,它的目標(biāo)是提供一種簡便的方式在 UI 層編寫響應(yīng)式代碼。
2,如果我們的序列滿足如下特征,就可以使用它:
不會(huì)產(chǎn)生 error 事件
一定在主線程監(jiān)聽(MainScheduler)
共享狀態(tài)變化(shareReplayLatestWhileConnected)
ControlProperty
1.是專門用來描述 UI 控件屬性,擁有該類型的屬性都是被觀察者(Observable)
2.ControlProperty 具有以下特征:
不會(huì)產(chǎn)生 error 事件
一定在 MainScheduler 訂閱(主線程訂閱)
一定在 MainScheduler 監(jiān)聽(主線程監(jiān)聽)
共享狀態(tài)變化
ControlEvent
1.是專門用于描述 UI 所產(chǎn)生的事件,擁有該類型的屬性都是被觀察者(Observable)。
2.ControlEvent 和 ControlProperty 一樣,都具有以下特征:
不會(huì)產(chǎn)生 error 事件
一定在 MainScheduler 訂閱(主線程訂閱)
一定在 MainScheduler 監(jiān)聽(主線程監(jiān)聽)
共享狀態(tài)變化
調(diào)度器
1.調(diào)度器(Schedulers)是 RxSwift 實(shí)現(xiàn)多線程的核心模塊,它主要用于控制任務(wù)在哪個(gè)線程或隊(duì)列運(yùn)行。
2.RxSwift 內(nèi)置了如下幾種 Scheduler:
CurrentThreadScheduler:表示當(dāng)前線程 Scheduler。(默認(rèn)使用這個(gè))
MainScheduler:表示主線程。如果我們需要執(zhí)行一些和 UI 相關(guān)的任務(wù),就需要切換到該 Scheduler運(yùn)行。
SerialDispatchQueueScheduler:封裝了 GCD 的串行隊(duì)列。如果我們需要執(zhí)行一些串行任務(wù),可以切換到這個(gè) Scheduler 運(yùn)行。
ConcurrentDispatchQueueScheduler:封裝了 GCD 的并行隊(duì)列。如果我們需要執(zhí)行一些并發(fā)任務(wù),可以切換到這個(gè) Scheduler 運(yùn)行。
OperationQueueScheduler:封裝了 NSOperationQueue。
subscribeOn決定數(shù)據(jù)序列的構(gòu)建函數(shù)在哪個(gè) Scheduler 上運(yùn)行。
observeOn該方法決定在哪個(gè) Scheduler 上監(jiān)聽這個(gè)數(shù)據(jù)序列。