从本篇开始开始讲解RxSwift的一些操作符(变化操作符、条件和布尔操作符、结合操作符等)。
今天我们主要讲解的就是变化操作符
变化操作符主要包括了8种,分别是Buffer、Window、Map、FlatMap、FlatMapLatest、ConcatMap、Scan、GroupBy
下面我们开始讲解每一个操作符的使用。
1、Buffer
Buffer 本称为缓冲集合,可以设置制定时间、缓存多少数据,然后发出数据,当然如果不够的也会发出数据。举个例子:
-
func RxSwiftBuffer() {
-
// buffer 缓冲集合
-
let subject =
PublishSubject<
String>()
-
// 1秒会缓冲3个一起以数组方式抛出。如果缓存不足3个,也会发出。
-
subject.buffer(timeSpan:
1,
count:
3, scheduler:
MainScheduler.instance).subscribe(onNext: {
-
print($
0)
-
}).disposed(by: disposeBag)
-
subject.onNext(
"1")
-
subject.onNext(
"2")
-
subject.onNext(
"3")
-
-
subject.onNext(
"a")
-
subject.onNext(
"b")
-
subject.onNext(
"c")
-
-
subject.onNext(
"A")
-
subject.onNext(
"B")
-
}
下面是执行的结果:
-
[
"1",
"2",
"3"]
-
[
"a",
"b",
"c"]
-
[
"A",
"B"]
-
[]
-
[]
-
[]
-
[]
-
[]
从结果可以开出,每隔1秒缓存3个数据,并将数据已集合的方式进行打印,如果数据不满足三条,则打印空集合。
2、Window
window 和 buffer 十分相似。buffer 是周期性的将缓存的元素集合发送出来,window 周期性的将元素集合以 Observable 的形态发送出来。下面举个例子:
-
func RxSwiftWindow() {
-
// window 和 buffer 十分相似。buffer 是周期性的将缓存的元素集合发送出来,window 周期性的将元素集合以 Observable 的形态发送出来。
-
// 同时 buffer要等到元素搜集完毕后,才会发出元素序列。而 window 可以实时发出元素序列。
-
let subject =
PublishSubject<
String>()
-
subject.window(timeSpan:
1,
count:
3, scheduler:
MainScheduler.instance).subscribe(onNext: { [
weak
self]
in
-
print(
"subscribe: \($0)")
-
$
0.asObservable().subscribe(onNext: {
-
print($
0)
-
}).disposed(by:
self!.disposeBag)
-
}).disposed(by: disposeBag)
-
-
subject.onNext(
"a")
-
subject.onNext(
"b")
-
subject.onNext(
"c")
-
// print("Resources.total ", RxSwift.Resources.total)
-
-
subject.onNext(
"1")
-
// print("Resources.total ", RxSwift.Resources.total)
-
subject.onNext(
"2")
-
subject.onNext(
"3")
-
// print("Resources.total ", RxSwift.Resources.total)
-
-
}
下面是执行结果:
-
subscribe:
RxSwift.
AddRef<
Swift.
String>
-
a
-
b
-
c
-
subscribe:
RxSwift.
AddRef<
Swift.
String>
-
1
-
2
-
3
-
subscribe:
RxSwift.
AddRef<
Swift.
String>
-
subscribe:
RxSwift.
AddRef<
Swift.
String>
-
subscribe:
RxSwift.
AddRef<
Swift.
String>
-
subscribe:
RxSwift.
AddRef<
Swift.
String>
从结果可以看出,window通过Observable的方式进行发送,对Observable的内容重新订阅才能拿到具体的内容,当然拿到的内容还是以及集合形式进行打印,如果Observable内容为空将不会获取到集合内容并打印。
3、Map
该操作符通过传入一个函数闭包把原来的 Observable 序列转变为一个新的 Observable 序列。和swift原声的map用法基本一致,下面上代码:
-
func RxSwiftMap() {
-
// 该操作符通过传入一个函数闭包把原来的 Observable 序列转变为一个新的 Observable 序列。和swift原声的map用法基本一致
-
// 相当于返回一个10倍的新序列
-
Observable.of(
1,
2,
3).
map { $
0 *
10 }.subscribe(onNext: {
-
print($
0)
-
}).disposed(by: disposeBag)
-
}
结果显而易见:
-
10
-
20
-
30
4、FlatMap
map 在做转换的时候容易出现“升维”的情况。即转变之后,从一个序列变成了一个序列的序列。
而FlatMap 操作符会对源 Observable 的每一个元素应用一个转换方法,将他们转换成 Observables。 然后将这些 Observables 的元素合并之后再发送出来。即又将其 "拍扁"(降维)成一个 Observable 序列。
这个操作符是非常有用的。比如当 Observable 的元素本生拥有其他的 Observable 时,我们可以将所有子 Observables 的元素发送出来。相当于合并了两个
-
func RxSwiftFlatMap() {
-
// map 在做转换的时候容易出现“升维”的情况。即转变之后,从一个序列变成了一个序列的序列。
-
// 而 flatMap 操作符会对源 Observable 的每一个元素应用一个转换方法,将他们转换成 Observables。 然后将这些 Observables 的元素合并之后再发送出来。即又将其 "拍扁"(降维)成一个 Observable 序列。
-
// 这个操作符是非常有用的。比如当 Observable 的元素本生拥有其他的 Observable 时,我们可以将所有子 Observables 的元素发送出来。
-
// 相当于合并了两个
-
-
let subject1 =
BehaviorSubject(value:
"A")
-
let subject2 =
BehaviorSubject(value:
"1")
-
let subject3 =
BehaviorSubject(value:
"中文")
-
-
let variable =
Variable(subject1)
-
variable.asObservable().flatMap { $
0 }.subscribe(onNext: {
-
print($
0)
-
}).disposed(by: disposeBag)
-
-
subject1.onNext(
"B")
-
subject1.onNext(
"C")
-
-
variable.value = subject2
//效果:log:1
-
-
subject1.onNext(
"D")
-
subject1.onNext(
"E")
-
-
-
variable.value = subject1
-
subject2.onNext(
"3")
-
subject2.onNext(
"4")
-
-
variable.value = subject1
-
subject2.onNext(
"3")
-
subject2.onNext(
"4")
-
-
// Whenever a new value is set, all the observers are notified of the change.
-
variable.value = subject3
-
subject3.onNext(
"中文2")
-
-
//所以,666依旧会导引出来。此时,subject1、subject2、subject3都是有效的observers
-
subject2.onNext(
"666")
-
}
-
A
-
B
-
C
-
1
-
D
-
E
-
E
-
3
-
4
-
E
-
3
-
4
-
中文
-
中文2
-
666
从结果可以看出,每次都会保留上一次的值,但重复值的时候,就会再次打印上一次的值,并且每个subject赋新值的时候也并不会影响其结果。
5、FlatMapLatest
flatMapLatest与flatMap 的唯一区别是:flatMapLatest只会接收最新的value 事件。这样最终就只会输出subject2,subject1就不会输出了
-
func RxSwiftFlatMapLatest() {
-
// flatMapLatest与flatMap 的唯一区别是:flatMapLatest只会接收最新的value 事件。
-
// 这样最终就只会输出subject2,subject1就不会输出了
-
-
let subject1 =
BehaviorSubject(value:
"A")
-
let subject2 =
BehaviorSubject(value:
"1")
-
-
let variable =
Variable(subject1)
-
-
variable.asObservable().flatMapLatest({ $
0 }).subscribe(onNext: {
-
print($
0)
-
}).disposed(by: disposeBag)
-
-
subject1.onNext(
"B")
-
variable.value = subject2
-
subject2.onNext(
"2")
-
subject1.onNext(
"C")
-
}
结果:
-
A
-
B
-
1
-
2
从结果可以看出,只要赋值新的subject,旧的subject的内容变化便不会再打印结果。
6、ConcatMap
concatMap 与 flatMap 的唯一区别是:当前一个 Observable 元素发送完毕后,后一个Observable 才可以开始发出元素。或者说等待前一个 Observable 产生完成事件后,才对后一个 Observable 进行订阅。
如果subject1不发送onCompleted,subject2永远不会输出
-
func RxSwiftConcatMap() {
-
// concatMap 与 flatMap 的唯一区别是:当前一个 Observable 元素发送完毕后,后一个Observable 才可以开始发出元素。或者说等待前一个 Observable 产生完成事件后,才对后一个 Observable 进行订阅。
-
// 如果subject1不发送onCompleted,subject2永远不会输出
-
-
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")
-
subject2.onNext(
"C")
-
subject1.onCompleted()
//只有前一个序列结束后,才能接收下一个序列
-
}
结果:
-
A
-
B
-
C
从结果很容易看出,在执行variable.value = subject2的时候,下面的next执行2、C都没有进行打印,只有当subject1.onCompleted()后,才会打印subject2的值,而且subject2的值只会打印最新的一次。
7、Scan
scan 就是先给一个初始化的数,然后不断的拿前一个结果和最新的值进行处理操作。
-
func RxSwiftScan() {
-
// scan 就是先给一个初始化的数,然后不断的拿前一个结果和最新的值进行处理操作
-
// 输出为1,3,6,10,15
-
// acum 为新值 elem为下一个值
-
Observable.of(
1,
2,
3,
4,
5).scan(
0) { acum, elem
in
-
acum + elem
-
}.subscribe(onNext: {
-
print($
0)
-
}).disposed(by: disposeBag)
-
}
结果:
-
1
-
3
-
6
-
10
-
15
8、GroupBy
groupBy 操作符将源 Observable 分解为多个子 Observable,然后将这些子 Observable 发送出来。
也就是说该操作符会将元素通过某个键进行分组,然后将分组后的元素序列以 Observable 的形态发送出来。
-
func RxSwiftGroupBy() {
-
// groupBy 操作符将源 Observable 分解为多个子 Observable,然后将这些子 Observable 发送出来。
-
// 也就是说该操作符会将元素通过某个键进行分组,然后将分组后的元素序列以 Observable 的形态发送出来。
-
// 将奇数偶数分成两组
-
Observable<
Int>.of(
0,
1,
2,
3,
4,
5).groupBy(keySelector: { element
in
-
return element %
2 ==
0 ?
"偶数" :
"奇数"
-
}).subscribe { (event)
in
-
switch event {
-
case .next(
let group):
-
group.asObservable().subscribe(onNext: { (event)
in
-
print(
"key:\(group.key) event:\(event)")
-
}).disposed(by:
self.disposeBag)
-
default:
-
print(
"")
-
}
-
}.disposed(by: disposeBag)
-
-
}
结果:
-
key:偶数 event:
0
-
key:奇数 event:
1
-
key:偶数 event:
2
-
key:奇数 event:
3
-
key:偶数 event:
4
-
key:奇数 event:
5
从结果可以看出,groupBy通过间0~5的值先进行了,奇偶书的分组,然后在对分完的内容进行了订阅。
到此操作变化符就介绍完成了,其实在开发过程中使用的频率并不高,但是也有使用的情况,这个看个人需要是要那个操作符。
下面是本人学习过程自己写的一个demo,感兴趣的小伙伴大家可以下载看一看。
转载:https://blog.csdn.net/WangQingLei0307/article/details/116049191