概述
在RxSwift的任何序列中,都可以用Observable描述,創(chuàng)建 -> 訂閱 -> 信號發(fā)送 -> 信號接收。
Observable<Any>.create { (observer) -> Disposable in
observer.onNext("信號1")
return Disposables.create()
}.subscribe(onNext: { (val) in
print("信號接收:\(val)")
}).disposed(by: disposeBag)
Observable是通用序列的描述符,調(diào)用.onNext,.onError,onCompleted來發(fā)送信號,具有很強的通用性。但是,當有業(yè)務需要特殊需求的時候,有可能會很復雜、繁瑣,所以,針對這種情況,RxSwift還為我們提供了一些特征序列,這些特征序列都是Observable序列的變種,能夠幫助我們更準確的去描述序列,比如有:Driver、Signal、ControlEvent、Single、Completable這些,這次,我們只介紹Driver這一個特征序列。
Driver
老司機帶帶我,有老司機帶你,讓你開車永遠不會出錯,
RxSwift提供的Driver序列不會提供error事件,而且一定是在主線程中監(jiān)聽,會向新的訂閱者發(fā)送上一次發(fā)送出的元素,主要就是為了簡化UI層的代碼,咱們來擼擼,為什么需要Driver的序列的存在。
比如說,咱們有一個這樣的需求:搜索框中每次輸入一個文本,就會獲取一次網(wǎng)絡請求,請求成功后將數(shù)據(jù)渲染到UI界面。
先來創(chuàng)建一個簡單的UI界面:
let textField = UITextField.init(frame: CGRect(x: 100, y: 100, width: 200, height: 40))
textField.borderStyle = .roundedRect
textField.placeholder = "請輸入搜索內(nèi)容"
self.view.addSubview(textField)
let label1 = UILabel.init(frame: CGRect(x: 100, y: 160, width: 200, height: 40))
label1.backgroundColor = .groupTableViewBackground
label1.textAlignment = .center
self.view.addSubview(label1)
let label2 = UILabel.init(frame: CGRect(x: 100, y: 210, width: 200, height: 40))
label2.backgroundColor = .groupTableViewBackground
label2.textAlignment = .center
self.view.addSubview(label2)
UI界面上,創(chuàng)建了一個textField,2個label用來展示。
接下來我們創(chuàng)建了一個網(wǎng)絡請求,代碼就不展示了,網(wǎng)絡請求一直以來都是耗時操作,所以,我們需要在異步線程中來完成網(wǎng)絡請求,直接發(fā)送序列,假如我們請求了一次網(wǎng)絡。
然后,我們需要實現(xiàn)textField輸入的監(jiān)聽,并且調(diào)取了網(wǎng)絡請求方法。
非Driver的實現(xiàn):
let result = textField.rx.text.orEmpty.skip(1)
.flatMap{return self.network(text: $0)
.observeOn(MainScheduler.instance)
.catchErrorJustReturn("網(wǎng)絡請求失敗")
}.share(replay: 1, scope: .whileConnected)
//網(wǎng)絡請求將發(fā)送多次請求
result.subscribe(onNext: { (val) in print("訂閱一:\(val) 線程:\(Thread.current)")
}).disposed(by: disposeBag)
result.subscribe(onNext: { (val) in print("訂閱二:\(val) 線程:\(Thread.current)")
}).disposed(by: disposeBag)
result.map{"\(($0 as! String).count)"}.bind(to: label1.rx.text).disposed(by: disposeBag)
result.map{"\($0)"}.bind(to: label2.rx.text).disposed(by: disposeBag)
observeOn選擇在哪個線程執(zhí)行catchErrorJustReturn錯誤處理,將onError事件轉(zhuǎn)為onNext事件share為多個觀察者共享資源,網(wǎng)絡請求只發(fā)送了一次,否則多個訂閱將會觸發(fā)多個請求
我們來看看Driver的實現(xiàn):
let result = textField.rx.text.orEmpty
.asDriver()
.flatMap {return self.network(text: $0).asDriver(onErrorJustReturn: "網(wǎng)絡請求失敗")
}
result.map{"長度:\(($0 as! String).count)"}
.drive(label1.rx.text).disposed(by: disposeBag)
result.map{"\($0)"}.drive(label2.rx.text).disposed(by: disposeBag)
asDriver()將序列轉(zhuǎn)換為Driver序列map重新組合并生成新的序列driver將元素在主線程中綁定到label1和label2上- 相比非
Driver下的代碼實現(xiàn),Driver序列省去了線程的設置,share數(shù)據(jù)共享設置。
我們斷點查看asDriver()方法:
extension ControlProperty {
/// Converts `ControlProperty` to `Driver` trait.
///
/// `ControlProperty` already can't fail, so no special case needs to be handled.
public func asDriver() -> Driver<Element> {
return self.asDriver { _ -> Driver<Element> in
#if DEBUG
rxFatalError("Somehow driver received error from a source that shouldn't fail.")
#else
return Driver.empty()
#endif
}
}
}
這是一個
ControlProperty的擴展方法,返回了一個Driver,它是SharedSequence的別名,是用來描述不同類型的序列,最后它又調(diào)用了self.asDriver方法,此方法是定義在ObservableConvertibleType的擴展方法中,追蹤下去,你會發(fā)現(xiàn),很多的類都是繼承于ObservableConvertibleType。
/**
Converts observable sequence to `Driver` trait.
- parameter onErrorRecover: Calculates driver that continues to drive the sequence in case of error.
- returns: Driver trait.
*/
public func asDriver(onErrorRecover: @escaping (_ error: Swift.Error) -> Driver<Element>) -> Driver<Element> {
let source = self
.asObservable()
.observeOn(DriverSharingStrategy.scheduler)
.catchError { error in
onErrorRecover(error).asObservable()
}
return Driver(source)
}
從上面的代碼,我們可以看到,調(diào)用了
observeOn方法,用于指定線程DriverSharingStrategy.scheduler,繼續(xù)往里面走,你就會發(fā)現(xiàn),它的內(nèi)部就是指定的主線程,這也說明了Driver的執(zhí)行就是在主線程。