RxSwfit 學(xué)習(xí)筆記(二)Observable & Observer

上一篇文章中,我們已經(jīng)簡(jiǎn)單了解了一下RxSwift入門的第一步,在RxCocoa的幫助下,來(lái)實(shí)現(xiàn)一個(gè)登錄輸入監(jiān)聽(tīng)校驗(yàn)的功能。
那么我們要如何創(chuàng)建一個(gè)屬于我們自己的監(jiān)聽(tīng)序列呢?或者說(shuō)如何監(jiān)聽(tīng)我們自己創(chuàng)建的屬性呢,比如說(shuō)一個(gè)String。

我們這里先簡(jiǎn)單說(shuō)一下Observable與Observer的區(qū)別與聯(lián)系

Observable:可監(jiān)聽(tīng)序列,從名字上來(lái)看,我們就能理解,他是用來(lái)被監(jiān)聽(tīng)的,而不是主動(dòng)監(jiān)聽(tīng)的

Observer:觀察者,顯而易見(jiàn),它與“可監(jiān)聽(tīng)序列”相對(duì),它就是用來(lái)監(jiān)聽(tīng)序列的角色。監(jiān)聽(tīng)事件,然后它需要這個(gè)事件做出響應(yīng)。例如:監(jiān)聽(tīng)到一個(gè)onNext事件,然后我們對(duì)這個(gè)事件作出響應(yīng)。

二者相互配合,從而達(dá)到響應(yīng)的效果。

Observable 可監(jiān)聽(tīng)序列

介紹內(nèi)容摘取自RxSwift的使用詳解3(Observable介紹、創(chuàng)建可觀察序列)
Observable 作為 Rx 的根基,我們首先對(duì)它要有一些基本的了解。

1. Observable<T>

  • Observable<T> 這個(gè)類就是Rx 框架的基礎(chǔ),我們可以稱它為可觀察序列。它的作用就是可以異步地產(chǎn)生一系列的 Event(事件),即一個(gè) Observable<T> 對(duì)象會(huì)隨著時(shí)間推移不定期地發(fā)出 event(element : T) 這樣一個(gè)東西。
  • 而且這些 Event 還可以攜帶數(shù)據(jù),它的泛型 <T> 就是用來(lái)指定這個(gè)Event攜帶的數(shù)據(jù)的類型。
  • 有了可觀察序列,我們還需要有一個(gè)Observer(訂閱者)來(lái)訂閱它,這樣這個(gè)訂閱者才能收到 Observable<T> 不時(shí)發(fā)出的 Event。

2.Event

查看 RxSwift 源碼可以發(fā)現(xiàn),事件 Event 的定義如下:

public enum Event<Element> {
    /// Next element is produced.
    case next(Element)
    /// Sequence terminated with an error.
    case error(Swift.Error)
    /// Sequence completed successfully.
    case completed
}

可以看到 Event 就是一個(gè)枚舉,也就是說(shuō)一個(gè) Observable 是可以發(fā)出 3 種不同類型的 Event 事件:

  • nextnext事件就是那個(gè)可以攜帶數(shù)據(jù) <T> 的事件,可以說(shuō)它就是一個(gè)“最正常”的事件。
  • errorerror 事件表示一個(gè)錯(cuò)誤,它可以攜帶具體的錯(cuò)誤內(nèi)容,一旦 Observable 發(fā)出了 error event,則這個(gè) Observable 就等于終止了,以后它再也不會(huì)發(fā)出 event 事件了。
  • completedcompleted 事件表示Observable 發(fā)出的事件正常地結(jié)束了,跟 error 一樣,一旦 Observable 發(fā)出了 completed event,則這個(gè) Observable 就等于終止了,以后它再也不會(huì)發(fā)出 event 事件了。

Observer 觀察者

在上文我們已經(jīng)有提到過(guò)了Observer就是用來(lái)“觀察”O(jiān)bservable的,那么是如何觀察的呢?
我們使用 subscribe() 方法來(lái)訂閱(觀察)Observable。
上面有提到Observable發(fā)出三種事件next、error、completed,那么Observer也對(duì)應(yīng)的能監(jiān)聽(tīng)到這三種事件

        //訂閱序列
        observable.subscribe(onNext: { (str) in
            print(str)
        }, onError: { (error) in
            print(error)
        }, onCompleted: {
            print("completed")
        }).disposed(by: disposebag)

Observable & Observer 配合使用

1. 最普通的序列創(chuàng)建與訂閱
        enum MyError: Error {
            case errorA
            case errorB
        }
        //創(chuàng)建序列
        let testOB = Observable<String>.create { ob in
            //發(fā)送next事件
            ob.onNext("test1")
            ob.onNext("test2")
            ob.onNext("test3")
            //發(fā)送error事件
            ob.onError(MyError.errorA)
            //發(fā)送completed事件
            ob.onCompleted()
            return Disposables.create()
        }
        
        //訂閱序列
        testOB.subscribe(onNext: { (str) in
            print(str)
        }, onError: { (error) in
            print(error)
        }, onCompleted: {
            print("completed")
        }).disposed(by: disposebag)

打印結(jié)果:

test1
test2
test3
errorA

細(xì)心的朋友已經(jīng)發(fā)現(xiàn)了,我們明明有發(fā)送completed,但是為什么沒(méi)有打印出來(lái),很明顯,問(wèn)題在ob.onError()上。
我們?cè)跍y(cè)試一下,挪動(dòng)一下ob.onError()的位置

        //創(chuàng)建序列
        let testOB = Observable<String>.create { ob in
            ob.onNext("test1")
            ob.onNext("test2")
            ob.onError(MyError.errorA)
            ob.onNext("test3")
            ob.onCompleted()
            return Disposables.create()
        }

打印結(jié)果:

test1
test2
errorA

所以我們能得出結(jié)論,一旦觀察者有監(jiān)聽(tīng)到error事件,那么就會(huì)在觸發(fā)onError:閉包結(jié)束后,停止監(jiān)聽(tīng)。后續(xù)應(yīng)該會(huì)好好聊聊這個(gè)問(wèn)題。我們先暫且了解就好。

2. 跨類使用

我們新創(chuàng)建一個(gè)類FirstViewModel,聲明一個(gè)Observable<String>類型的變量,然后在初始化方法中直接創(chuàng)建出來(lái)。

class FirstViewModel {
    var text : Observable<String>!
    
    let disposeBag = DisposeBag()
    init() {
        text  = Observable.create { (observer) -> Disposable in
            observer.onNext("test1")
            observer.onNext("test2")
            observer.onNext("test3")
            observer.onCompleted()
            return Disposables.create()
        }
    }
}

然后我們?cè)诳刂破髦?,初始?code>FirstViewModel

class FirstViewController: UIViewController {

    var disposeBag = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let vm : FirstViewModel = FirstViewModel.init()
        vm.text.subscribe(onNext: { obString in
            print(obString)
        }, onCompleted: {
            print("completed")
        }).disposed(by: disposeBag)
    }
}

command + R 看 輸出結(jié)果

msg1
msg2
msg3
completed
3. 點(diǎn)擊按鈕發(fā)送事件
class FirstViewModel {
   class func getText() -> Observable<String> {
        //創(chuàng)建一個(gè)just事件
        return  .just("你收到了嘛")
    }
}
btn.rx.tap.subscribe(onNext: { [weak self] in
    self?.btnClick()
}).disposed(by: disposeBag)
        
//事件
func btnClick() -> Void{
    FirstViewModel.getText().subscribe(onNext: { (String) in
        print(String)//輸出結(jié)果: 你收到了嘛
    }).disposed(by: disposeBag)
}

這里出現(xiàn)了一個(gè).just,這是什么呢。
創(chuàng)建Observable序列的方法有很多種。

創(chuàng)建Observable 序列其他方法

各個(gè)方法的區(qū)別于作用,可以看這里

        print("----------- this is just ----------- ")
        
        let observable_just = Observable<Int>.just(5)
        observable_just.subscribe(onNext: { (Int) in
            print("\(Int)")
        }, onCompleted: {
            print("just completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is of ----------- ")
        let observable_of = Observable.of("A", "B", "C")
        observable_of.subscribe(onNext: { (String) in
            print("\(String)")
        }, onCompleted: {
            print("of completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is from ----------- ")
        let observable_from = Observable.from(["A", "B", "C"])
        observable_from.subscribe(onNext: { (String) in
            print("\(String)")
        }, onCompleted: {
            print("from completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is empty ----------- ")
        let observable_empty = Observable<Int>.empty()
        observable_empty.subscribe(onNext: { (Int) in
            print("this is empty")
        }, onCompleted: {
            print("empty completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is never ----------- ")
        let observable_nerver = Observable<Int>.never()
        observable_nerver.subscribe(onNext: { (Int) in
            print("this is never")
        }, onCompleted: {
            print("never completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is error ----------- ")
        enum MyError: Error {
            case A
            case B
        }
        
        let observable_error = Observable<Int>.error(MyError.A)
        observable_error.subscribe(onNext: { (Int) in
            
        }, onError: { (Error) in
            print(" \(Error)")
        }, onCompleted: {
            print("error completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is range ----------- ")
        let observable_range = Observable.range(start: 1, count: 5)
        observable_range.subscribe(onNext: { (Int) in
            print("\(Int)")
        }, onCompleted: {
            print("range completed")
        }).disposed(by: disposeBag)
        
        //不能放在主線程,會(huì)堵塞
//        let observable_repeat = Observable.repeatElement(1)
//        observable_repeat.subscribe(onNext: { (Int) in
//            print("this is repeat -- \(Int)")
//        }, onCompleted: {
//            print("repeat completed")
//        }).disposed(by: disposeBag)
        
        print("----------- this is generate ----------- ")
        //使用generate()方法
        let observable_generate = Observable.generate(
            initialState: 0,
            condition: { $0 <= 10 },
            iterate: { $0 + 2 }
        )
        observable_generate.subscribe(onNext: { (Int) in
             print("\(Int)")
        }, onCompleted: {
            print("generate completed")
        }).disposed(by: disposeBag)
        
        print("----------- this is deferred ----------- ")
        //用于標(biāo)記是奇數(shù)、還是偶數(shù)
        var isOdd = true
        
        //使用deferred()方法延遲Observable序列的初始化,通過(guò)傳入的block來(lái)實(shí)現(xiàn)Observable序列的初始化并且返回。
        let factory : Observable<Int> = Observable.deferred {
            
            //讓每次執(zhí)行這個(gè)block時(shí)候都會(huì)讓奇、偶數(shù)進(jìn)行交替
            isOdd = !isOdd
            
            //根據(jù)isOdd參數(shù),決定創(chuàng)建并返回的是奇數(shù)Observable、還是偶數(shù)Observable
            if isOdd {
                return Observable.of(1, 3, 5 ,7)
            }else {
                return Observable.of(2, 4, 6, 8)
            }
        }
        
        //第1次訂閱測(cè)試
        factory.subscribe { event in
            print("\(isOdd)", event)
        }.disposed(by: disposeBag)
        
        //第2次訂閱測(cè)試
        factory.subscribe { event in
            print("\(isOdd)", event)
        }.disposed(by: disposeBag)
        //第3次訂閱測(cè)試
        factory.subscribe { event in
            print("\(isOdd)", event)
        }.disposed(by: disposeBag)
        
        print("----------- this is interval ----------- ")
        let observable_interval = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
        
        observable_interval.subscribe { event in
            print(event)
        }.disposed(by: disposeBag)
        
        print("----------- this is timer ----------- ")
        //5秒種后發(fā)出唯一的一個(gè)元素0
        let observable_timer = Observable<Int>.timer(5, scheduler: MainScheduler.instance)
        observable_timer.subscribe { event in
            print(event)
        }.disposed(by: disposeBag)
        
        //延時(shí)5秒種后,每隔1秒鐘發(fā)出一個(gè)元素
        let observable_timer2 = Observable<Int>.timer(5, period: 1, scheduler: MainScheduler.instance)
        observable_timer2.subscribe { event in
            print(event)
        }.disposed(by: disposeBag)

既是Observable 又是 Observer

怎么說(shuō)呢,像TextField,我們既可以監(jiān)聽(tīng)它,又可以把它當(dāng)做一個(gè)觀察者。

  • 如果是初學(xué)者,那么覺(jué)得上面這句話很奇怪,這個(gè)作為觀察者是什么意思?
    我們可以這么理解,我們既可以監(jiān)聽(tīng)文本框的輸入,又可以給文本框賦值。

那么接下來(lái)我就為你們介紹一下這種情況。

class FifthViewController: UIViewController {
    var textF:UITextField!
    
    let disposeBag = DisposeBag()
    override func viewDidLoad() {
        super.viewDidLoad()

        textF = UITextField.init(frame: .init(x: 20, y: 120, width: view.frame.width, height: 40))
        textF.borderStyle = .roundedRect
        view.addSubview(textF)
      
        //把文本框當(dāng)做觀察者
        let observer = textF.rx.text
        
        let text:Observable<String> = Observable<String>.create {
            $0.onNext("test")
            $0.onNext("test1")
            $0.onNext("test2")
            return Disposables.create()
        }
        text.bind(to: observer).disposed(by: disposeBag)
        
        //把文本框當(dāng)做可監(jiān)聽(tīng)對(duì)象
        let observable = textF.rx.text
        observable.subscribe(onNext: {
            print($0 as Any)
        }).disposed(by: disposeBag)
        
    }
}

另外,框架里面定義了一些輔助類型,它們既是可監(jiān)聽(tīng)序列也是觀察者。如果你能合適的應(yīng)用這些輔助類型,它們就可以幫助你更準(zhǔn)確的描述事物的特征:

  • AsyncSubject
  • PublishSubject
  • ReplaySubject
  • BehaviorSubject
  • ControlProperty”

摘錄來(lái)自: RxSwift 中文文檔。

以上幾種輔助類型我將在 RxSwfit 學(xué)習(xí)筆記(四)中學(xué)習(xí)探索

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

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

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