美文网首页RxSwift学习selector
iOS 【Swift-PublishSubject、AsyncS

iOS 【Swift-PublishSubject、AsyncS

作者: NJ_墨 | 来源:发表于2021-08-25 09:44 被阅读0次
Subjects 介绍

Subjects 是订阅者,也是Observable:
订阅者:它能动态的接收新的值。
Observable: 当Subjects有了新值后会通过Event将新值发出给他的所有订阅者。

Subjects 有四种:PublishSubject、BehaviorSubject、ReplaySubject、Variable

相同点
都是Observable,他们的订阅者都能接收他们发出的新的Event
直到 Subject 发出 .complete 或者 .error 的 Event 后,该 Subject 便终结了,同时它也就不会再发出.next事件。
在Subject 终结后再订阅他的订阅者,也能收到 subject发出的一条.complete 或.error的event,

不同点
PublishSubject
最普通的Subject,不需要初始值就能初始化。
他的订阅者只能收到他们订阅后的 Event。


enum MyError: Error {
    case A
    case B
    var errorType: String {
        switch self {
        case .A:
            return "error A"
        case .B:
            return "error B"
        }
    }
}

let disposeBag = DisposeBag()
PublishSubject将发送订阅后产生的元素,而之前元素将不会发送给观察者
结束之后添加的订阅能收到 completed
结束后发的都收不到

func testPublishSubject() {
        let publicSubject = PublishSubject<Int>()
        publicSubject.onNext(1)  //没有输出
        publicSubject.subscribe { e in
            print(e.element ?? 0)
        }.disposed(by: disposeBag)
        
        publicSubject.onNext(2) //输出:2
        publicSubject.onNext(3) //输出:3
        publicSubject.onCompleted() //输出:0
        publicSubject.subscribe { event in
            print(event)
        }.disposed(by: disposeBag) //输出:completed
        publicSubject.onNext(4) //无
}

AsyncSubject 将在源 Observable 产生完成事件后,发出最后一个元素(仅仅只有最后一个元素),
如果源 Observable 没有发出任何元素,只有一个完成事件

    func testAsyncSubject() {
       
        let asyncSubject = AsyncSubject<String>()
        
        asyncSubject.subscribe { e in
            print((e.element ?? "xx") as String)
            //print(e.element)
        }.disposed(by: disposeBag)
        
        asyncSubject.onNext("A")
        asyncSubject.onNext("B")
        asyncSubject.onNext("C")  //执行
        asyncSubject.onCompleted()//执行
        //输出:
        //C
        //xx
    }

AsyncSubject如果源 Observable 因为产生了一个 error 事件而中止,
就不会发出任何元素,而是将这个 error 事件发送出来

    func testAsyncError() {
      
        let asyncSubject = AsyncSubject<String>()
        
        asyncSubject.subscribe { e in
            print(e)
            
        }.disposed(by: disposeBag)
        
        asyncSubject.onNext("A1")
        asyncSubject.onNext("B1")
        asyncSubject.onNext("C1")
        asyncSubject.onError(MyError.A) //执行
        asyncSubject.onCompleted()
        //输出:
        //error(A)
    }

ReplaySubject 将发送全部的元素,无论是何时进行订阅的
结束后订阅,不仅会收到最后的n个 event 还有 Completed

    func testReplaySubject() {
        //多个版本的 ReplaySubject,有的只会将最新的 n 个元素发送给观察者,有的只会将 限制时间段内 最新的元素发送给观察者
        //如果把 ReplaySubject 当作观察者来使用,注意不要在多个线程调用 onNext, onError 或 onCompleted。这样会导致无序调用,将造成意想不到的结果
        let replaySubject = ReplaySubject<String>.create(bufferSize: 2)
        
        replaySubject.onNext("1")
        replaySubject.onNext("2")
        replaySubject.onNext("3")

        replaySubject.subscribe { (e) in
            print(e.element ?? "")
        }.disposed(by: disposeBag)

        replaySubject.onNext("A")
        replaySubject.onNext("B")
        replaySubject.onNext("C")
       replaySubject.onCompleted()
        print("-------")
        /// 不仅会收到最后的两个 event 还有 Completed
        replaySubject.subscribe { event in
            print("订阅4", event)
        }.disposed(by: disposeBag)
        //输出:
        /**
         2
         3
         A
         B
         C
         -------
         订阅4 next(B)
         订阅4 next(C)
         订阅4 completed
         */
    }
    

BehaviorSubject 它会将最新的元素 发送出来(如果不存在最新的,就发出默认元素)。
需要一个默认值初始化
一个订阅者订阅之后会立马收到上一个Event,之后就是正常情况发一个收一个

   func testBehaviorSubject() {
       //如果源 Observable 因为产生了一个 error 事件而中止, BehaviorSubject 就不会发出任何元素,而是将这个 error 事件发送出来
      
       print("===========")
       let subject = BehaviorSubject(value: "默认")
       
       //subject.onNext("1")
       //subject.onNext("2")
       // 前面两个<注释>了,这个时候,发送默认元素
       subject.subscribe { (e) in
           print("(1) \(e.element ?? "")")
       }.disposed(by: disposeBag)

       subject.onNext("A")
       subject.onNext("B")

       subject.subscribe { (e) in
           print("(2) \(e.element ?? "")")
       }.disposed(by: disposeBag)

       subject.onNext("C")
       subject.onNext("D")
       
       //输出:
       /**
        (1) 默认
        (1) A
        (1) B
        (2) B
        (1) C
        (2) C
        (1) D
        (2) D
        */
   }

ControlPropertyUI相关的
UITextField .rx.text.subscribe默认会执行一次,可以跳过.skip(1)或.changed

//Label根据TextField内容改变
//1
self.textField.rx.text.bind(to: self.testLabel.rx.text).disposed(by: disposeBag)
//2
self.textField.rx.text.subscribe { (event: Event<String?>) in
            //将UITextField文字改变的内容显示在Label中
            self.testLabel.text = event.element!
            print(event.element!!)}.disposed(by:disposeBag)
//3
self.textField.rx.text.subscribe(onNext: { (str: String?) in    self.testLabel.text = str!}).disposed(by:disposeBag)
self.textField.rx.text.skip(1).subscribe(onNext: { (str: String?) in    self.testLabel.text = str!}).disposed(by:disposeBag)
self.textField.rx.text.changed.subscribe(onNext: { (str: String?) in    self.testLabel.text = str!}).disposed(by:disposeBag)


//4 监听label内容的改变
 self.testLabel.rx.observe(String.self, "text").subscribe(onNext: { (str: String?) in    print(str!)}).disposed(by:disposeBag)
//5 监听frame的改变(约束不行)
self.testLabel.rx.observe(CGRect.self, "frame").subscribe(onNext: { (rect: CGRect?) in print(rect!.height)}).disposed(by:disposeBag)

相关文章

网友评论

    本文标题:iOS 【Swift-PublishSubject、AsyncS

    本文链接:https://www.haomeiwen.com/subject/pfljiltx.html