RxSwift学习-06-高阶函数(下)

374 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

  • 本文继续介绍RxSwift中的高阶函数的使用。

1.集合操控控制符

1. toArray

toArray:把一个可观察的序列转换为一个数组,将该数组作为一个新的数组元素发出,之后终止。

Observable.of(1,2,3,4,5)

            .toArray()

            .subscribe(onSuccess: { arr in

                print(arr)

            }, onFailure: { error in

                print(error)

            }, onDisposed: {

                print("disposed")

            })

            .disposed(by: disposBag)

打印结果:[1,2,3,4,5]

1.2 reduce

reduce:从一个初始化的值开始,然后对一个可观察序列发出所有元素操作符的闭包,将结果单个元素的形式返回

Observable.of(1,10,100)

            .reduce(1, accumulator: +)

            .subscribe { num in

                print(num)

            } onError: { error in

                print(error)

            } onCompleted: {

                print("completer")

            } onDisposed: {

                print("disposed")

            }

            .disposed(by: disposBag)

打印结果:112,一般用于数组的累加或者累减操作

1.3 concat

concat:以顺序方式连接来自一个可观察序列的内部可观察序列的元素,在从下一个序列发出元素之前等待每个序列成功终止


        let sub1 = BehaviorSubject(value: 1)

        let sub2 = BehaviorSubject(value: 2)

        

        let subjectsSubject = BehaviorSubject(value: sub1)

        subjectsSubject.asObserver()

            .concat()

            .subscribe(onNext: { num in

                print(num)

            }, onError: { err in

                print(err)

            }, onCompleted: {

                print("completed")

            }, onDisposed: {

                print("disposed")

            })

            .disposed(by: disposBag)

        sub1.onNext(3)

        sub1.onNext(4)

        subjectsSubject.onNext(sub2)//切换源

        sub2.onNext(5)

        sub2.onNext(6)//保存最新发送的序列信号元素

        sub1.onCompleted()// sub1 完成后才能收到订阅

        sub2.onNext(7)

        

        //可以通过concat进行异步网络请求,控制顺序

打印结果:

image.png 一般用于控制顺序

2. 从错误序列中恢复序列

一般我们发送错误信号会结束序列,从可观察对象的错误通知中恢复的操作符。

2.1 catchAndReturn

用于处理自定义返回的错误样式,比我我们网络请求错误,我们可以通过catchAndReturn返回我们自定义错误信息

let errorSequence = PublishSubject<String>()


        errorSequence.catchAndReturn("fish")

            .subscribe { str in

                print(str)

            } onError: { error in

                print(error)

            } onCompleted: {

                print("completed")

            } onDisposed: {

                print("disposed")

            }.disposed(by: disposBag)


        errorSequence.onNext("good")

        errorSequence.onNext("friend")


        errorSequence.onError(NSError.init(domain: "networkError", code: 400))

打印结果:

image.png

2.2 catch

catch: 和上面的catchAndReturn类似,只是我们要自己返回一个Observable的序列

let errorSequence = PublishSubject<String>()

        errorSequence.catch(<#T##handler: (Error) throws -> Observable<String>##(Error) throws -> Observable<String>#>)

        errorSequence.catch { error in

            return Observable.of("fish")

        }.subscribe { str in

                print(str)

            } onError: { error in

                print(error)

            } onCompleted: {

                print("completed")

            } onDisposed: {

                print("disposed")

            }.disposed(by: disposBag)

效果和上面一样

2.3 retry

retry :通过无限的重新订阅可观察序列来恢复重复的错误事件

var count = 1 //外界变了控制流程

        

        let sequenceRetryErrors = Observable<String>.create { ob in

            

            ob.onNext("fish1")

            

            ob.onNext("fish2")

            

            ob.onNext("fish3")


            if count == 1{

                

                ob.onError(NSError.init(domain: "networkError", code: 400))

                count += 1

            }

            

            ob.onNext("go")

            ob.onNext("hello")

            

            ob.onCompleted()

            return Disposables.create()

        }

        

        sequenceRetryErrors.retry()

            .subscribe { str in

                print(str)

            } onError: { error in

                print(error)

            } onCompleted: {

                print("completed")

            } onDisposed: {

                print("disposed")

            }.disposed(by: disposBag)

接收到了错误序列,重试序列发生,打印结果:

image.png

2.4 retry(_ : )

相比retry 于retry(_ : )填写重复的次数,当到达重复次数后就会发送error信号

var count = 1 //外界变了控制流程


let sequenceThatErrors = Observable<String>.create { ob in

                        ob.onNext("fish1")

            

                        ob.onNext("fish2")

            

                        ob.onNext("fish3")

            

                        if count < 5{

            

                            ob.onError(NSError.init(domain: "networkError", code: 400))

                            count += 1

                        }

            

                        ob.onNext("go")

                        ob.onNext("hello")

            

                        ob.onCompleted()

                        return Disposables.create()

                    }

            sequenceThatErrors.retry(2)

            .subscribe(onNext: {print($0)})

            .disposed(by: disposBag)

打印结果:

image.png

相当于重复2次调用序列的闭包subscribeHandler

3. Rx流程操作符

3.1 debug

debug模式下打印所有序列事件

image.png

对于有多个debug我们可以自定义它的名字用于区分

image.png

3.2 RxSwift.Resources.total

RxSwift.Resources.total提供所有Rx资源分配的计数,用于开发期间检测泄漏默认使用``RxSwift.Resources.total会报错,需要修改pod文件,修改完毕之后重新pod ,然后编译就可以了

image.png

post_install do |installer|

  installer.pods_project.targets.each do |target|

    if target.name == 'RxSwift'

      target.build_configurations.each do |config|

        if config.name == 'Debug'

          config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['-D', 'TRACE_RESOURCES']

        end

      end

    end

  end

end

使用

print(RxSwift.Resources.total)


        let disposeBag = DisposeBag()//使用2

        print(RxSwift.Resources.total)

        Observable.of("total")

            .subscribe(onNext: {print($0)})

            .disposed(by: disposeBag)

        print(RxSwift.Resources.total)

        let subject = BehaviorSubject(value: "hello")

        let subscription1 = subject.subscribe(onNext: { print($0) })

        print(RxSwift.Resources.total)

        let subscription2 = subject.subscribe(onNext: { print($0) })

        print(RxSwift.Resources.total)

        subscription1.dispose()


        print(RxSwift.Resources.total)

        subscription2.dispose()


        print(RxSwift.Resources.total)

打印结果:

image.png

4. 链接操作符

4.1 connect

connect : 将源可观察序列转换为可连接序列,并通过指定的主题广播其发射。

        print("beging")

        let ob = Observable<Any>.create { observer in

            sleep(2)

            observer.onNext("start")

            observer.onCompleted()

            return Disposables.create()

        }.publish()

        ob.subscribe(onNext: {print($0)})

            .disposed(by: disposBag)

        

        ob.subscribe(onNext: {print($0)})

            .disposed(by: disposBag)

        _ = ob.connect()

打印结果:

image.png

效果等同于share(),共享状态。

4.2 replay

replay: 将源可观察序列转换为可连接的序列,并将向每个新订阅服务器重放以前排放的缓冲大小
首先拥有和publish一样的能力,共享 Observable sequence, 其次使用replay还需要我们传入一个参数(buffer size)来缓存已发送的事件,当有新的订阅者订阅了,会把缓存的事件发送给新的订阅者


        

        let interval = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance).replay(5)

        

        interval.subscribe(onNext: { print(Date.now,"订阅: 1, 事件: \($0)") })

            .disposed(by: self.disposeBag)

        

        delay(2) { _ = interval.connect() }

        

        delay(4) {

            interval.subscribe(onNext: { print(Date.now,"订阅: 2, 事件: \($0)") })

                .disposed(by: self.disposeBag)

        }

        

        delay(8) {

            interval.subscribe(onNext: { print(Date.now,"订阅: 3, 事件: \($0)") })

                .disposed(by: self.disposeBag)

        }

        delay(20, closure: {

            self.disposeBag = DisposeBag()

        })
        
        /// 延迟几秒执行

    func delay(_ delay: Double, closure: @escaping () -> Void) {

        DispatchQueue.main.asyncAfter(deadline: .now() + delay) {

            closure()

        }

    }

打印结果:

image.png

  • 使用push 共享一个Observable的事件序列,避免创建多个Observable sequence。 注意:需要调用connect之后才会开始发送事件

image.png

  • 没有共享序列

image.png 可以发现序列最后被订阅三次产生了3个定时器相当于,各自独立打印订阅信息。

5. 总结

以上就是一些高阶函数的使用,我们实际使用并不会每一个都使用到,或者我们通过组合的方式达到高阶函数的效果。这里记录下,温故知新。