RxSwift(五)-- RxSwift特征序列Driver

概述

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、ControlEventSingle、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將元素在主線程中綁定到label1label2
  • 相比非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í)行就是在主線程。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容