RxSwift--高阶函数

本文详细介绍了RxSwift中的高阶函数,包括组合类、映射类、过滤条件、集合控制、错误恢复、Debug和链接操作符等。重点讨论了startWith、merge、zip、map、flatMap、filter、take、skip等关键操作符的使用场景和区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

本文着重介绍RxSwift高阶函数的使用,高阶函数很多,但没必要所有都熟练记忆,比较重要的能够熟练记忆并使用,不常用的用到了临时查询即可。

一、组合类操作符

1.startWith

在开始从可观察源发出元素之前,发出指定的元素序列。

Observable.of("1", "2", "3", "4")
            .startWith("A")
            .startWith("B")
            .startWith("C", "a", "b")
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
//输出: CabBA1234

2.merge

将源可观察序列中的元素组合成一个新的可观察序列,并将像每个源可观察序列发出元素一样发出每个元素。

let subject1 = PublishSubject<String>()
        let subject2 = PublishSubject<String>()
        // merge subject1和subject2
        Observable.of(subject1, subject2)
            .merge()
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        
        subject1.onNext("H")
        subject1.onNext("e")
        subject2.onNext("l")
        subject2.onNext("l")
        subject1.onNext("o")
        subject2.onNext("")
        //输出:Hello

注: 任何一个响应都会勾起新序列响应

3.zip

将指定个数的源可观测序列组合成一个新的可观测序列,并将从组合的可观测序列中发射出对应索引处每个源可观测序列的元素。

let stringSubject = PublishSubject<String>()
        let intSubject = PublishSubject<Int>()
        Observable.zip(stringSubject, intSubject) { stringElement, intElement in
                "\(stringElement) \(intElement)"
            }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        
        stringSubject.onNext("H")
        stringSubject.onNext("e") //到这里存储了H、o但是不会响应,除非另一个响应
        intSubject.onNext(1) // 输出一个
        intSubject.onNext(2) // 输出另一个
        stringSubject.onNext("l") // 存一个
        intSubject.onNext(3) // 输出一个
        //只有两个序列同时有值的时候才会响应,否则存值

注: 只有两个序列同时有值的时候才会响应,否则存值。

4.combineLatest

将指定个数的源可观测序列组合成一个新的观测序列,并将最近的元素覆盖。

5.switchLatest

将可观察序列发出的元素转换为可观察序列,并从最近的内部可观察序列发出元素。

二、映射类操作符

1.map

转换闭包应用于可观察序列发出的元素,并返回转换后的元素的新可观察序列。

let ob = Observable.of(1,2,3,4)
        ob.map { (number) -> Int in
            return number+2
            }
            .subscribe{
                print("\($0)")
            }
            .disposed(by: disposeBag)

2.flatMap & flatMapLatest

将可观测序列发射的元素转换为可观测序列,并将两个可观测序列的发射合并为一个可观测序列。
例如,当你有一个可观察的序列,它本身发出可观察的序列,你想能够对任何一个可观察序列的新发射做出反应(序列中序列:比如网络序列中还有模型序列)
flatMap和flatMapLatest的区别是,flatMapLatest只会从最近的内部可观测序列发射元素。
flatMapLatest实际上是map和switchLatest操作符的组合。

let boy  = LGPlayer(score: 100)
        let girl = LGPlayer(score: 90)
        let player = BehaviorSubject(value: boy)
        
        player.asObservable()
            .flatMap { $0.score.asObservable() } // 本身score就是序列 模型就是序列中的序列
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        boy.score.onNext(60)
        player.onNext(girl)
        boy.score.onNext(50)
        boy.score.onNext(40)//  如果切换到 flatMapLatest 就不会打印
        girl.score.onNext(10)
        girl.score.onNext(0)

3.scan

从初始就带有一个默认值开始,然后对可观察序列发出的每个元素应用累加器闭包,并以单个元素可观察序列的形式返回每个中间结果。这里主要强调序列值之间的关系。

Observable.of(10, 100, 1000)
            .scan(2) { aggregateValue, newValue in
                aggregateValue + newValue // 10 + 2 , 100 + 10 + 2 , 1000 + 100 + 2
            }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

三、过滤条件操作符

1.filter

仅从满足指定条件的可观察序列中发出那些元素。

Observable.of(1,2,3,4,5,6,7,8,9,0)
            .filter { $0 % 2 == 0 }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

2.distincUntilChanged

抑制可观察序列发出的顺序重复元素。

 Observable.of("1", "2", "2", "2", "3", "3", "4")
            .distinctUntilChanged()
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

3.elementAt

仅在可观察序列发出的所有元素的指定索引处发出元素。

Observable.of("C", "o", "o", "c", "i")
            .elementAt(3)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

4.single

只发出可观察序列发出的第一个元素(或满足条件的第一个元素)。如果可观察序列发出多个元素,将抛出一个错误。

	Observable.of("Apple", "Banana")
            .single()
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        
    Observable.of("Apple", "Banana")
            .single { $0 == "Banana" }
            .subscribe { print($0) }
            .disposed(by: disposeBag)

5.take

只从一个可观察序列的开始发出指定数量的元素。

Observable.of("A", "B","C", "D")
            .take(2)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

6.takeLast

仅从可观察序列的末尾发出指定数量的元素。

Observable.of("A", "B","C", "D")
            .takeLast(3)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

7.takeWhile

只要指定条件的值为true,就从可观察序列的开始发出元素

Observable.of(1, 2, 3, 4, 5, 6)
            .takeWhile { $0 < 3 }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

8.takeUntil

从源可观察序列发出元素,直到参考可观察序列发出元素.这个要重点,应用非常频繁 比如我页面销毁了,就不能获取值了(cell重用运用)。

let sourceSequence = PublishSubject<String>()
        let referenceSequence = PublishSubject<String>()
        
        sourceSequence
            .takeUntil(referenceSequence)
            .subscribe { print($0) }
            .disposed(by: disposeBag)
        
        sourceSequence.onNext("A")
        sourceSequence.onNext("B")
        sourceSequence.onNext("C")
        referenceSequence.onNext("Stop-Condition") 
        //条件一出来,下面就走不了
        sourceSequence.onNext("D")
        sourceSequence.onNext("E")
        sourceSequence.onNext("F")

9.skip

跳过指定个数的元素,开始发出元素。从源可观察序列发出元素,直到参考可观察序列发出元素.这个要重点,应用非常频繁 不用解释 textfiled 都会有默认序列产生。

Observable.of(1, 2, 3, 4, 5, 6)
            .skip(2)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

10.skipWhile

从满足条件的位置开始发出元素。

Observable.of(1, 2, 3, 4, 5, 6)
            .skipWhile { $0 < 4 }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

11.skipUntil

抑制从源可观察序列发出元素,直到参考可观察序列发出元素。
代码类似takeUntil。

四、集合控制操作符

1.toArray

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

Observable.range(start: 1, count: 10)
            .toArray()
            .subscribe { print($0) }
            .disposed(by: disposeBag)

2.reduce

从一个设置的初始化值开始,然后对一个可观察序列发出的所有元素应用累加器闭包,并以单个元素可观察序列的形式返回聚合结果。类似scan。

  Observable.of(10, 100, 1000)
            .reduce(1, accumulator: +) // 1 + 10 + 100 + 1000 = 1111
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

3.contact

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

  let subject1 = BehaviorSubject(value: "Apple")
        let subject2 = BehaviorSubject(value: "1")
        
        let subjectsSubject = BehaviorSubject(value: subject1)
        
        subjectsSubject.asObservable()
            .concat()
            .subscribe { print($0) }
            .disposed(by: disposeBag)
        
        subject1.onNext("Banana")
        subject1.onNext("Orange")
        
        subjectsSubject.onNext(subject2)
        
        subject2.onNext("打印不出来")
        subject2.onNext("2")
        
        subject1.onCompleted() // 必须要等subject1 完成了才能订阅到! 用来控制顺序 网络数据的异步
        subject2.onNext("3")

五、从可观察对象的错误通知中恢复的操作符

1.catchErrorJustReturn

从错误事件中恢复,方法是返回一个可观察到的序列,该序列发出单个元素,然后终止。

 let sequenceThatFails = PublishSubject<String>()
        
        sequenceThatFails
            .catchErrorJustReturn("Apple")
            .subscribe { print($0) }
            .disposed(by: disposeBag)
        
        sequenceThatFails.onNext("Banana")
        sequenceThatFails.onNext("Orange") // 正常序列发送成功的
        sequenceThatFails.onError(self)

2.catchError

通过切换到提供的恢复可观察序列,从错误事件中恢复

   let recoverySequence = PublishSubject<String>()
        
        sequenceThatFails
            .catchError {
                print("Error:", $0)
                return recoverySequence  // 获取到了错误序列-我们在中间的闭包操作处理完毕,返回给用户需要的序列(showAlert)
            }
            .subscribe { print($0) }
            .disposed(by: disposeBag)
        
        sequenceThatFails.onNext("Apple")
        sequenceThatFails.onNext("Banana") // 正常序列发送成功的
        sequenceThatFails.onError(lgError) // 发送失败的序列
        
        recoverySequence.onNext("Orange”)

3.retry

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

4.retry( _: )

通过重新订阅可观察到的序列,重复地从错误事件中恢复,直到重试次数达到max未遂计数

六、Debug Rx流程操作符

1.debug

打印所有订阅、事件和处理。

var count = 1
        let sequenceThatErrors = Observable<String>.create { observer in
            observer.onNext("A")
            observer.onNext("B")
            observer.onNext("C")
            
            if count < 5 {
                observer.onError(self.lgError)
                print("错误序列来了")
                count += 1
            }
            
            observer.onNext("D")
            observer.onNext("E")
            observer.onNext("F")
            observer.onCompleted()
            
            return Disposables.create()
        }
        
        sequenceThatErrors
            .retry(3)
            .debug()
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

2.RxSwift.Resources.total

提供所有Rx资源分配的计数,这对于在开发期间检测泄漏非常有用。

七、链接操作符

1.multicast

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

2.replay

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

3.push

将源可观察序列转换为可连接序列.共享一个Observable的事件序列,避免创建多个Observable sequence。
注意:需要调用connect之后才会开始发送事件.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JeffersonGO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值