RxSwift学习(四)--- RxSwift 高阶函数

RxSwift 高阶函数

今天我们来探索下RxSwift高阶函数,和一些组合函数的用法

组合操作符

startWith()
  • 在开始从可观察源发出元素之前,发出指定的元素序列
  • elements:要附加到指定序列的元素
  • returns: 返回以指定值开头的源序列
public func startWith(_ elements: Self.E...) -> RxSwift.Observable<Self.E>
Observable<String>.of("1","2","3")
            .startWith("a")
            .startWith("b")
            .subscribe(onNext: { (element) in
                Log(element)
            }).disposed(by: self.disposeBag)
//打印值 : b a 1 2 3
merge()
  • 将源可观察序列中的元素组合成一个新的可观察序列,并将像每个源可观察序列发出元素一样发出每个元素
  • maxConcurrent:同时订阅的内部可观察序列的最大数量
  • returns:返回 合并内部序列元素的可观察序列
public func merge(maxConcurrent: Int) -> RxSwift.Observable<Self.E.E>

使用例子:

print("*****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("J")
        subject1.onNext("a")
        subject2.onNext("d")
   	// 打印
   	// J
   	// a
   	// d

 let subject1 = PublishSubject<String>()
        let subject2 = PublishSubject<String>()
        let subject3 = PublishSubject<String>()
        let subject4 = PublishSubject<String>()
        // merge subject1和subject2
        Observable.of(subject1, subject2,subject3,subject4)
            .merge(maxConcurrent: 2)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

        subject1.onNext("J")
        subject1.onNext("a")
        subject2.onNext("d")
        subject2.onNext("e")
        subject3.onNext("k")
        subject4.onNext("i")
   //打印
   // J
   // a
   // d
   // e

maxConcurrent设置为2的时候,我们发现subject3subject4的数据打印不出来,以此证明maxConcurrent这个参数限制的是观察者序列的个数,而不是总的赋值个数

zip()
  • 将多达8个源可观测序列组合成一个新的可观测序列,并将从组合的可观测序列中发射出对应索引处每个源可观测序列的元素
  • 说白了: 只有两个序列同时有值的时候才会响应,否则存值
  • source1、source2: 元素
  • resultSelector: 在源中的相应索引处调用每个元素系列的函数
  • returns:可观察的序列,包含使用指定的结果选择器功能合并源元素的结果
public static func zip<O1, O2>(_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.E, O2.E) throws -> Self.E) -> RxSwift.Observable<Self.E> where O1 : RxSwift.ObservableType, O2 : RxSwift.ObservableType

使用例子:

		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("C")
        stringSubject.onNext("o") // 到这里存储了 C o 但是不会响应除非;另一个响应
        // print nil
        
        intSubject.onNext(1) // 勾出一个
        // print C 1
        intSubject.onNext(2) // 勾出另一个
        /*
         print
         C 1
         o 2
         */
        stringSubject.onNext("i") // 存一个
        /*
         print
         C 1
         o 2
         */
        intSubject.onNext(3) // 勾出一个
        /*
         print
         C 1
         o 2
         i 3
         */
        // 说白了: 只有两个序列同时有值的时候才会响应,否则存值
combineLatest()
  • 每当任何可观察序列产生一个元素时,通过使用选择器功能将指定的可观察序列合并为一个可观察序列
  • source1、source2: 元素
  • resultSelector: 每当任何源产生元素时要调用的函数数
  • returns:可观察的序列,包含使用指定的结果选择器功能合并源元素的结果
  • 应用非常频繁: 比如账户和密码同时满足->才能登陆. 不关系账户密码怎么变化的只要查看最后有值就可以 loginEnable
public static func combineLatest<O1, O2>(_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.E, O2.E) throws -> Self.E) -> RxSwift.Observable<Self.E> where O1 : RxSwift.ObservableType, O2 : RxSwift.ObservableType

使用例子:

let stringSub = PublishSubject<String>()
        let intSub = PublishSubject<Int>()
        Observable.combineLatest(stringSub, intSub) { strElement, intElement in
                "\(strElement) \(intElement)"
            }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

        stringSub.onNext("L") // 存一个 L
        stringSub.onNext("G") // 存了一个覆盖 - 和zip不一样
        // print nil
        intSub.onNext(1)      // 发现intSub也有G 响应 G 1
        // print G 1
        intSub.onNext(2)      // 覆盖1 -> 2 发现intSub 有值G 响应 G 2
        // print G 2
        stringSub.onNext("Jadekirin") // 覆盖G -> Jadakirin 发现intSub 有值2 响应 Jadekirin 2
        // print Jadekirin 2
        // 

combineLatest 相比zip 会覆盖

switchLatest()
  • 将可观察序列发出的元素转换为可观察序列,并从最近的内部可观察序列发出元素
public func switchLatest() -> RxSwift.Observable<Self.E.E>

使用例子:

		let switchLatestSub1 = BehaviorSubject(value: "L")
        let switchLatestSub2 = BehaviorSubject(value: "1")
        let switchLatestSub  = BehaviorSubject(value: switchLatestSub1)// 选择了 switchLatestSub1 就不会监听 switchLatestSub2

        switchLatestSub.asObservable()
            .switchLatest()
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)

        switchLatestSub1.onNext("T")
        switchLatestSub1.onNext("B")
        switchLatestSub2.onNext("2")
        switchLatestSub2.onNext("3") // 2-3都会不会监听,但是默认保存由 2覆盖1 3覆盖2
        // print L T B
        
        switchLatestSub.onNext(switchLatestSub2) // 切换到 switchLatestSub2
        switchLatestSub1.onNext("*") // 不会被打印
        // Print L T B 3
        
        switchLatestSub1.onNext("H") // 不会被打印但是 H 会覆盖 *  原理同上面 下面如果再次切换到 switchLatestSub1会打印出 H
        
        switchLatestSub2.onNext("4")
        // Print L T B 3 4
        switchLatestSub.onNext(switchLatestSub1)
        // Print L T B 3 4 H

变换操作符

map()
  • 转换闭包应用于可观察序列发出的元素,并返回转换后的元素的新可观察序列
  • transform: 应用于每个源元素的转换函
  • returns: 一个可观察的序列,其元素是调用源的每个元素上的转换函数的结果
public func map<R>(_ transform: @escaping (Self.E) throws -> R) -> RxSwift.Observable<R>

使用例子:

	let _ = Observable.of(1,2,3,4)
            .map { $0 + 1 }
            .subscribe { Log($0) }
            .disposed(by: self.disposeBag)
        
        // 2 3 4 5
flatMap() and flatMapLatest()
  • 将可观测序列发射的元素转换为可观测序列,并将两个可观测序列的发射合并为一个可观测序列。
  • 这个操作符是非常有用的。比如当 Observable 的元素本生拥有其他的 Observable 时,我们可以将所有子 Observables 的元素发送出来。
  • 这也很有用,例如,当你有一个可观察的序列,它本身发出可观察的序列,你想能够对任何一个可观察序列的新发射做出反应(序列中序列:比如网络序列中还有模型序列)
  • flatMapflatMapLatest的区别是,flatMapLatest只会从最近的内部可观测序列发射元素,也就是最新的序列元素
  • flatMapLatest实际上是mapswitchLatest操作符的组合
public func flatMap<O>(_ selector: @escaping (Self.E) throws -> O) -> RxSwift.Observable<O.E> where O : RxSwift.ObservableConvertibleType

public func flatMapLatest<O>(_ selector: @escaping (Self.E) throws -> O) -> RxSwift.Observable<O.E> where O : RxSwift.ObservableConvertibleType

使用例子:

 let boy  = BehaviorSubject(value: "10")
        let girl = BehaviorSubject(value: "A")
        let player = BehaviorSubject(value: boy)

        player.asObservable()
            .flatMap { $0 } // 本身score就是序列 模型就是序列中的序列
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        boy.onNext("60")
        player.onNext(girl)
        girl.onNext("B")
        boy.onNext("50")
        // 10 60 A B

		
		// 换成 flatMapLatest
        player.asObservable()
            .flatMapLatest { $0 }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        
        boy.onNext("60")
        player.onNext(girl)
        girl.onNext("B")
        boy.onNext("50")
        boy.onNext("40")//  如果切换到 flatMapLatest 就不会打印
        girl.onNext("C")	

		// 10 60 A B C 

我们发现用flatMapLatest的时候,40 、50就不打印了。
这就说明flatMapLatest只会从最近的内部可观测序列发射元素,就是说切换到girl以后就会舍弃boy

concatMap()
  • 将可观测序列的每个元素编程到可观测序列中,并将生成的可观测序列串联到一个可观测序列中
  • concatMapflatMap 的唯一区别是:当前一个 Observable 元素发送完毕后,后一个Observable 才可以开始发出元素。或者说等待前一个 Observable产生完成事件后,才对后一个 Observable 进行订阅
 public func concatMap<O>(_ selector: @escaping (Self.E) throws -> O) -> RxSwift.Observable<O.E> where O : RxSwift.ObservableConvertibleType

使用例子:

		let subject1 = BehaviorSubject(value: "A")
        let subject2 = BehaviorSubject(value: "1")
         
        let variable = Variable(subject1)
         
        variable.asObservable()
            .concatMap { $0 }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
         
        subject1.onNext("B")
        variable.value = subject2
        subject2.onNext("2")
        subject1.onNext("C")
        subject1.onCompleted()

		// A B C 2

只有subject1执行完以后 subject2才开始执行

buffer()
  • 该方法简单来说就是缓存 Observable 中发出的新元素,当元素达到某个数量,或者经过了特定的时间,它就会将这个元素集合发送出来
  • timeSpan:缓冲区的最大时间长度
  • count:缓冲区的最大元素计数
  • scheduler:计划程序运行缓冲计时器
  • returns:可观察到的缓冲区序列
public func buffer(timeSpan: RxSwift.RxTimeInterval, count: Int, scheduler: RxSwift.SchedulerType) -> RxSwift.Observable<[Self.E]>

使用例子:

let subject = PublishSubject<String>()
        
        //每缓存3个元素则组合起来一起发出。
        //如果1秒钟内不够3个也会发出(有几个发几个,一个都没有发空数组 [])
        subject
           .buffer(timeSpan: 1, count: 3, scheduler: MainScheduler.instance)
           .subscribe(onNext: { print($0) })
           .disposed(by: disposeBag)

        subject.onNext("a")
        subject.onNext("b")
        subject.onNext("c")
        
        subject.onNext("1")
        subject.onNext("2")
		/*
		["a", "b", "c"]
		["1", "2"]
		[]
		[]
		*/
scan()
  • 从初始就带有一个默认值开始,然后对可观察序列发出的每个元素应用累加器闭包,并以单个元素可观察序列的形式返回每个中间结果
  • 这里主要强调序列值之间的关系
  • seed: 初始值
  • accumulator: 要在每个元素上调用的累加器函数
  • returns: 包含累积值的可观察序列
public func scan<A>(_ seed: A, accumulator: @escaping (A, Self.E) throws -> A) -> RxSwift.Observable<A>

使用例子:

Observable.of(1,3,5)
            .scan(4) { (aggre, newValue) in
                aggre + newValue
            }
            .subscribe({Log($0)})
            .disposed(by: self.disposeBag)
		
		//4+1		5
        //4+1+3		8
        //4+1+3+5	13

过滤条件操作符

filter()
  • 仅满足指定条件的可观察序列中发出那些元素
  • predicate:用于测试每个源元素的条件的函数。
  • returns:包含满足条件的输入序列中的元素的可观察序列
public func filter(_ predicate: @escaping (Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>

使用例子:

	Observable.of(1,3,4,5,23,46)
            .filter({$0 % 2 == 0})
            .subscribe(onNext: {Log($0)})
            .disposed(by: self.disposeBag)

	//print 4 46
distinctUntilChanged()
  • 过滤可观察序列发出的顺序(连续)重复的元素
public func distinctUntilChanged() -> RxSwift.Observable<Self.E>

使用例子:

Observable.of(1,2,2,3,3,4,3,3,5,4,5)
            .distinctUntilChanged()
            .subscribe(onNext: {Log($0)})
            .disposed(by: self.disposeBag)
        // 1 2 3 4 3 5 4 5
elementAt()
  • 仅在可观察序列发出的所有元素的指定索引处发出元素(就是打印出指定索引的元素)
  • index: 所需元素的索引(从 0 开始)
  • returns: 将所需元素作为其唯一发射物发出的可观测序列
public func elementAt(_ index: Int) -> RxSwift.Observable<Self.E>
	Observable.of(10,20,30,50)
            .elementAt(3)
            .subscribe(onNext: {Log($0)})
            .disposed(by: self.disposeBag)
        // 50
single()
  • 只发出可观察序列发出的第一个元素(或满足条件的第一个元素)。
  • 如果可观察序列发出多个元素,将抛出一个错误。
public func single() -> RxSwift.Observable<Self.E>
	Observable.of("C", "K")
            .single{ $0 == "K"}
            .subscribe(onNext: { print($0) }) 
            .disposed(by: disposeBag)
        // K 
        Observable.of("C", "K")
            .single()
            .subscribe(onNext: { print($0) }) //发出的第一个元素
            .disposed(by: disposeBag)
        // C
        
        Observable.of("J", "H","G")
            .single { $0 == "H" || $0 == "J" }
            .subscribe(onNext: {Log($0)}, onError: { (error) in
                Log("报错--\(error)")
            })
            .disposed(by: disposeBag)
        // J 满足条件的第一个元素
        // 报错--Sequence contains more than one element.
take()
  • 只从一个可观察序列的开始发出指定数量的元素(最前面的元素)。
  • 在满足数量之后会自动.completed
  • count: 要返回的元素数
public func take(_ count: Int) -> RxSwift.Observable<Self.E>
	Observable.of("H", "K","C", "L")
            .take(2)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
		// H K
takeLast()
  • 仅从可观察序列的末尾发出指定数量的元素
  • count: 要从源序列末尾执行的元素数。
public func takeLast(_ count: Int) -> RxSwift.Observable<Self.E>
	Observable.of("H", "K","C", "L")
            .takeLast(2)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        // C L
        
takeWhile()
  • 只要指定条件的值为true,就从可观察序列的开始发出元素
  • predicate:用于测试每个元素的条件的函数
public func takeWhile(_ predicate: @escaping (Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>
	Observable.of(1,2,3,4,5,6,7,8)
            .takeWhile({$0 < 4})
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
		// 1 2 3 
takeUntil()
  • 从源可观察序列发出元素,直到参考可观察序列发出元素
  • 这个比较重点,应用非常频繁 比如我页面销毁了,就不能获取值了(cell重用运用)
  • other:终止源序列元素传播的可观察序列。
  • returns:包含源序列元素的可观察序列,一个到其他序列中断进一步传播的点
public func takeUntil<O>(_ other: O) -> RxSwift.Observable<Self.E> where O : RxSwift.ObservableType
let sourceSequence = PublishSubject<String>()
        let referenceSequence = PublishSubject<String>()

        sourceSequence
            .takeUntil(referenceSequence)
            .subscribe { print($0) }
            .disposed(by: disposeBag)

        sourceSequence.onNext("A")
        sourceSequence.onNext("K")
        sourceSequence.onNext("C")

        referenceSequence.onNext("H") // 条件一出来,下面就走不了
		sourceSequence.onNext("L")	
		
		// A K C  completed

referenceSequence 条件已执行,就不会往下执行了

Skip()
  • 从源可观察序列发出元素,直到参考可观察序列发出元素
  • 应用非常频繁 不用解释 textfiled 都会有默认序列产生
  • 输出不符合条件的元素
  • 和take相反
  • count: 返回其余元素之前要跳过的元素数
public func skip(_ count: Int) -> RxSwift.Observable<Self.E>
		Observable.of(1, 2, 3, 4, 5, 6)
            .skip(2)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        // 3 4 5 6
skipWhile()
  • 只要指定条件的值为false,就从可观察序列的开始发出元素
  • predicate:用于测试每个元素的条件的函数
  • takeWhile相反
public func skipWhile(_ predicate: @escaping (Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>
	Observable.of(1, 2, 3, 4, 5, 6)
            .skipWhile { $0 < 4 }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposeBag)
        // 4 5 6
skipUntil()
  • 抑制从源可观察序列发出元素,直到参考可观察序列发出元素
  • takeUntil 相反
  • other:开始传播源序列元素的可观察序列。
public func skipUntil<O>(_ other: O) -> RxSwift.Observable<Self.E> where O : RxSwift.ObservableType
	let sourceSequence = PublishSubject<String>()
        let referenceSequence = PublishSubject<String>()

        sourceSequence
            .skipUntil(referenceSequence)
            .subscribe { print($0) }
            .disposed(by: disposeBag)

        sourceSequence.onNext("A")
        sourceSequence.onNext("K")
        sourceSequence.onNext("C")
        referenceSequence.onNext("H") // 条件一出来,下面就开始了
        sourceSequence.onNext("L")       
        //print  L
ignoreElements()
  • 该操作符可以忽略掉所有的元素,只发出 errorcompleted 事件
  • 如果我们并不关心 Observable 的任何元素,只想知道 Observable 在什么时候终止,那就可以使用 ignoreElements 操作符。
	Observable.of(1, 2, 3, 4)
    .ignoreElements()
    .subscribe{
        print($0)
    }disposed(by: disposeBag)
    // completed

还有很多高阶函数,后续会再行探索

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值