RxSwift学习(四)--- RxSwift 高阶函数
- RxSwift学习(一)— RxSwift介绍
- RxSwift学习(二)— Observable 常见的序列创建方法
- RxSwift学习(三)— Observer、Binder、Subjects、BehaviorRelay
- RxSwift学习(四)— RxSwift 高阶函数
- 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) inLog(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和subject2Observable.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和subject2Observable.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
的时候,我们发现subject3
和subject4
的数据打印不出来,以此证明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 nilintSubject.onNext(1) // 勾出一个// print C 1intSubject.onNext(2) // 勾出另一个/*printC 1o 2*/stringSubject.onNext("i") // 存一个/*printC 1o 2*/intSubject.onNext(3) // 勾出一个/*printC 1o 2i 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") // 存一个 LstringSub.onNext("G") // 存了一个覆盖 - 和zip不一样// print nilintSub.onNext(1) // 发现intSub也有G 响应 G 1// print G 1intSub.onNext(2) // 覆盖1 -> 2 发现intSub 有值G 响应 G 2// print G 2stringSub.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 就不会监听 switchLatestSub2switchLatestSub.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 BswitchLatestSub.onNext(switchLatestSub2) // 切换到 switchLatestSub2switchLatestSub1.onNext("*") // 不会被打印// Print L T B 3switchLatestSub1.onNext("H") // 不会被打印但是 H 会覆盖 * 原理同上面 下面如果再次切换到 switchLatestSub1会打印出 HswitchLatestSub2.onNext("4")// Print L T B 3 4switchLatestSub.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
的元素发送出来。 - 这也很有用,例如,当你有一个可观察的序列,它本身发出可观察的序列,你想能够对任何一个可观察序列的新发射做出反应(序列中序列:比如网络序列中还有模型序列)
flatMap
和flatMapLatest
的区别是,flatMapLatest
只会从最近的内部可观测序列发射元素,也就是最新的序列元素flatMapLatest
实际上是map
和switchLatest
操作符的组合
public func flatMap<O>(_ selector: @escaping (Self.E) throws -> O) -> RxSwift.Observable<O.E> where O : RxSwift.ObservableConvertibleTypepublic 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// 换成 flatMapLatestplayer.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()
- 将可观测序列的每个元素编程到可观测序列中,并将生成的可观测序列串联到一个可观测序列中
concatMap
与flatMap
的唯一区别是:当前一个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 = subject2subject2.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) inaggre + 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)// CObservable.of("J", "H","G").single { $0 == "H" || $0 == "J" }.subscribe(onNext: {Log($0)}, onError: { (error) inLog("报错--\(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()
- 该操作符可以忽略掉所有的元素,只发出
error
或completed
事件 - 如果我们并不关心
Observable
的任何元素,只想知道Observable
在什么时候终止,那就可以使用ignoreElements
操作符。
Observable.of(1, 2, 3, 4).ignoreElements().subscribe{print($0)}disposed(by: disposeBag)// completed
还有很多高阶函数,后续会再行探索
RxSwift学习(四)--- RxSwift 高阶函数相关推荐
- python学习——函数式编程——高阶函数
python学习--函数式编程--高阶函数 函数式编程(高阶函数):1:map && reduce; 2 : filter; 3: sorted; ------------------ ...
- python学习总结1—高阶函数
python 高阶函数学习 高阶函数 介绍python 高阶函数的使用方法 map/reduce函数 map函数 利用map()函数,把用户输入的不规范的英文名字,变为首字母大写,其他小写的规范名字. ...
- Kotlin学习三:高阶函数
目录 一.高阶函数的基本概念 二.常见高阶函数 1.关于list映射 2.flatMap 3.综合1 4.综合2 三.尾递归优化 四.闭包 五.函数复合 六.科理化 七.偏函数 八.小案例 一.高阶函 ...
- Python学习日志10 - 高阶函数和高级应用
Python学习日志 RBHGO的主页欢迎关注 温馨提示:创作不易,如有转载,注明出处,感谢配合~ 目录 文章目录 Python学习日志 目录 前言 进入正题 Python学习日志10课 - 高阶函数 ...
- 【廖雪峰Python学习笔记】高阶函数
Higher-order function 高阶函数 映射 过滤算法 排序算法 高阶函数 变量可指向函数 >>> abs # 函数 <built-in function abs ...
- Python学习之Part09.高阶函数filter(),map(),reduce(),sorted()
1.高阶函数 一个函数作为参数传给另外一个函数: 一个函数的返回值为另外一个函数(若返回值为该函数本身,则为递归) # abs()用来求一个数的绝对值 # 将abs函数赋值,则f==abs f = a ...
- 廖雪峰讲python高阶函数求导公式_廖雪峰的学习笔记(三)高阶函数
1.所谓的"高阶函数":把函数对象作为参数的函数. 2.示例: map()函数: 我们先看map.map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数 ...
- python六十四课——高阶函数练习题(一)
1.lt = ['sdfasdfa', 'ewqrewrewqr', 'dsafa12312fdsafd', 'safsadf'] --> 得到长度列表2.tp = ('TOM', 'Lilei ...
- python匿名函数调用_python3笔记十六:python匿名函数和高阶函数
一:学习内容 lambda函数 map函数与reduce函数 filter函数 sorted函数 二:匿名函数-lambda 1.概念:不使用def这样的语句去定义函数,使用lambda来创建匿名函数 ...
- JavaScript 面向对象编程(三) —— 函数进阶 / 严格模式 / 高阶函数 / 闭包 / 浅拷贝和深拷贝
本篇为 JavaScript 进阶 ES6 系列笔记第三篇,将陆续更新后续内容.参考:JavaScript 进阶面向对象 ES6 :ECMAScript 6 入门 系列笔记: JavaScript 面 ...
最新文章
- Android 多点触控 MotionEvent详解
- android调试推荐使用BlueStacks模拟器调试Android应用
- 2.1 基于文件读写图像数据
- Access导入MDB文件
- 信息系统项目管理师优秀论文:项目采购管理
- CF750E-New Year and Old Subsequence【动态dp】
- Codeforces Round #356 (Div. 1) D. Bear and Chase 暴力
- 故宫门票预订网站崩溃;岳云鹏信息打包卖 100 元;华为要做电视?| 极客头条...
- DNS 系统解析过程概述
- Debian 9 Stretch国内常用镜像源
- SVG 动画(animate、animateTransform、animateMotion)
- Synchronized的底层实现原理(看这篇就够了)
- MyEclipse2014安装aptana插件
- nc文件的读取与写入
- 每日一词20190313——地图矢量化
- 软素质面试题分享以及一些面试技巧和面试礼仪
- 炼丹笔记三:数据增强
- 2022茶艺师(中级)考题及模拟考试
- scrapy 爬取煎蛋网图片
- python的文件操作、模块操作、os模块、time、datatime模块以及模块的制作