这篇主要介绍在《RxSwift 中文文档》中,未被分类的操作符。
delay
顾名思义,就是延时发送。
将产生的每一个元素,拖延一段时间后再发出。
案例
class EightViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
Observable.just("延迟发送出来的元素")
.delay(.seconds(3), scheduler: MainScheduler.instance) //元素延迟3秒才发出
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
}
}
注意:用delay的时候,disposeBag需要是一个属性,不能是一个临时变量,否则将会失效
delaySubscription
这个用起来跟delay几乎一模一样,但是本质上的区别是
delay是延时发送
delaySubscription是延时订阅
案例
Observable.just("这是延时订阅")
.delaySubscription(.seconds(3), scheduler: MainScheduler.instance) //延迟3秒才开始订阅
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
materialize
将序列产生的事件,转换成元素
通常,一个有限的 Observable 将产生零个或者多个 onNext 事件,然后产生一个 onCompleted 或者 onError 事件。
materialize 操作符将 Observable 产生的这些事件全部转换成元素,然后发送出来。
不好意会,我们看下面两个案例对比
Observable.just("这是materialize")
.materialize()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
/*
输出结果:
next(这是materialize)
completed
*/
Observable.just("这是materialize")
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
/*
输出结果:
这是materialize
*/
一对比就明显了,materialize发出来的是事件,而不是对应的值。
如果用了materialize还是要获取值就这样操作
Observable.just("这是materialize")
.materialize()
.subscribe(onNext: { (event) in
print(event.element!)
})
.disposed(by: disposeBag)
还有另外一种方式 dematerialize
dematerialize
dematerialize跟materialize正好相反,可以理解成解码跟编码的关系。
案例
Observable.just("这是materialize")
.materialize()
.dematerialize()
.subscribe(onNext: { string in
print(string!)
})
.disposed(by: disposeBag)
timeout
如果源 Observable 在规定时间内没有发出任何元素,就产生一个超时的 error 事件
如果 Observable 在一段时间内没有产生元素,timeout 操作符将使它发出一个 error 事件。
案例
Observable.just("这是延时订阅")
.delaySubscription(.seconds(3), scheduler: MainScheduler.instance) //延迟3秒才开始订阅
.timeout(.seconds(2), scheduler: MainScheduler.instance)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
输出结果:
Unhandled error happened: Sequence timeout.
subscription called from:
ignoreElements
忽略掉所有的next事件,只发出 error 或 completed 事件
ignoreElements 操作符将阻止 Observable 发出 next 事件,但是允许他发出 error 或 completed 事件。
如果你并不关心 Observable 的任何元素,你只想知道 Observable 在什么时候终止,那就可以使用 ignoreElements 操作符。
当我们要订阅的时候,会发现提示中并不包含onNext
startWith
将一些元素插入到序列的头部
startWith 操作符会在 Observable 头部插入一些元素。
案例
let disposeBag = DisposeBag()
Observable.of("🐶", "🐱", "🐭", "🐹")
.startWith("1")
.startWith("2")
.startWith("3", "🅰️", "🅱️")
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
打印结果:
3
🅰️
🅱️
2
1
🐶
🐱
🐭
🐹
buffer
缓存元素,然后将缓存的元素集合,周期性的发出来
buffer 操作符将缓存 Observable 中发出的新元素,当元素达到某个数量,或者经过了特定的时间,它就会将这个元素集合发送出来。
就是
buffer会将我们发出的元素,按照一定的数量,将他们组合成数组,然后再一起发出来。
案例
let subject = PublishSubject<String>()
subject
.buffer(timeSpan: .seconds(3), count: 3, scheduler: MainScheduler.instance)
.timeout(.seconds(2), scheduler: MainScheduler.instance)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
打印结果:
["a", "b", "c"]
["1", "2", "3"]
["1", "2", "3"]
["1", "2", "3"]
["1", "2", "3"]
Unhandled error happened: Sequence timeout.
subscription called from:
//如果没有设置`timeout`那么后续他将会发出,按设定的时间每次发出一个空数组。
[]
[]
[]
window
将 Observable 分解为多个子 Observable,周期性的将子 Observable 发出来
window操作符和 buffer十分相似,buffer周期性的将缓存的元素集合发送出来,而 window 周期性的将元素集合以 Observable 的形态发送出来。
buffer要等到元素搜集完毕后,才会发出元素序列。而 window可以实时发出元素序列。
案例
let subject = PublishSubject<String>()
subject
.window(timeSpan: .seconds(3), count: 3, scheduler: MainScheduler.instance)
.timeout(.seconds(2), scheduler: MainScheduler.instance)
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
打印结果:
RxSwift.AddRef<Swift.String>
RxSwift.AddRef<Swift.String>
RxSwift.AddRef<Swift.String>
Unhandled error happened: Sequence timeout.
subscription called from:
由结果看来,他确实如文档所说,打印的只是一些成组的序列。
那么我们在给这个$0加上订阅会如何呢
let subject = PublishSubject<String>()
subject
.window(timeSpan: .seconds(3), count: 3, scheduler: MainScheduler.instance)
.timeout(.seconds(2), scheduler: MainScheduler.instance)
.subscribe(onNext: {
$0.subscribe(onNext: { print($0) })
}).disposed(by: disposeBag)
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
打印结果:
1
2
3
1
2
3
groupBy
将源 Observable 分解为多个子 Observable,并且每个子 Observable 将源 Observable 中“相似”的元素发送出来
groupBy 操作符将源 Observable 分解为多个子 Observable,然后将这些子 Observable 发送出来。
它会将元素通过某个键进行分组,然后将分组后的元素序列以 Observable 的形态发送出来。
案例
Observable<Int>.of(0, 1, 2, 3, 4, 5,3,2,1)
.groupBy(keySelector: { (element) -> String in
return element % 2 == 0 ? "偶数" : "基数"
})
.subscribe { (event) in
print(event)
switch event {
case .next(let group):
group.asObservable().subscribe({ (event) in
print("key: \(group.key) \(event)")
})
default:
print("")
}
}
.dispose()
打印结果:
key: 基数 next(1)
key: 偶数 next(2)
key: 基数 next(3)
key: 偶数 next(4)
key: 基数 next(5)
key: 基数 next(3)
key: 偶数 next(2)
key: 基数 next(1)
key: 偶数 completed
key: 基数 completed
completed
single
限制 Observable 只有一个元素,否出发出一个 error事件
single操作符将限制 Observable 只产生一个元素。如果 Observable 只有一个元素,它将镜像这个 Observable 。如果 Observable 没有元素或者元素数量大于一,它将产生一个error 事件。
如果发送的数量大于1或者 什么都没做,就发出一个错误事件
案例
Observable.of(1,2,3)
.single()
.subscribe{
print($0)
}.disposed(by: disposeBag)
打印结果:
next(1)
error(Sequence contains more than one element.)
amb
在多个源 Observables 中, 取第一个发出元素或产生事件的 Observable,然后只发出它的元素
当你传入多个 Observables 到 amb 操作符时,它将取其中一个 Observable:第一个产生事件的那个 Observable,可以是一个 next,error 或者 completed 事件。 amb 将忽略掉其他的 Observables。
当同时监听多个Observable 时,选择其中一个,即
amb(b),就不监听另外一个。
案例
let a = BehaviorSubject(value: "🐱")
let b = BehaviorSubject(value: "🐶")
Observable.of(a,b)
.flatMap{$0}
.amb(b)
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
a.onNext("🐦")
b.onNext("🐔")
a.onNext("🦆")
打印结果:
🐶
🐔
reduce
持续的将 Observable 的每一个元素应用一个函数,然后发出最终结果
reduce 操作符将对第一个元素应用一个函数。然后,将结果作为参数填入到第二个元素的应用函数中。以此类推,直到遍历完全部的元素后发出最终结果。
这种操作符在其他地方有时候被称作是accumulator,aggregate,compress,fold 或者 inject。
案例
let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
.reduce(2, accumulator: *)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
打印结果:
打印结果 = 1 * 2 * 3 * 2 = 12
do
当 Observable 产生某些事件时,执行某个操作
当 Observable 的某些事件产生时,你可以使用 do 操作符来注册一些回调操作。这些回调会被单独调用,它们会和 Observable 原本的回调分离。
案例
Observable.of(1, 2, 3)
.do(onNext: { element in
print("do next:" ,element)
}, onError: { error in
print("do error:", error)
}, onCompleted: {
print("do completed")
}, onSubscribe: {
print("do subscribe")
}, onSubscribed: {
print("do subscribed")
}, onDispose: {
print("do dispose")
})
.subscribe { event in
switch event {
case .next(let element):
print("element:", element)
case .error(let error):
print("error:", error)
case .completed:
print("completed")
}}
.disposed(by: disposeBag)
打印结果:
do subscribe
do subscribed
do element: 1
element: 1
do element: 2
element: 2
do element: 3
element: 3
do completed
completed
do dispose
using
创建一个可被清除的资源,它和 Observable 具有相同的寿命
通过使用 using 操作符创建 Observable 时,同时创建一个可被清除的资源,一旦 Observable 终止了,那么这个资源就会被清除掉了。
案例
//一个无限序列(每隔0.1秒创建一个序列数 )
let infiniteInterval = Observable<Int>
.interval(0.1, scheduler: MainScheduler.instance)
.do(
onNext: { print("infinite: \($0)") },
onSubscribe: { print("开始订阅 infinite")},
onDispose: { print("销毁 infinite")}
)
//一个有限序列(每隔0.5秒创建一个序列数,共创建三个 )
let limited = Observable<Int>
.interval(0.5, scheduler: MainScheduler.instance)
.take(2)
.do(
onNext: { print("limited: \($0)") },
onSubscribe: { print("开始订阅 limited")},
onDispose: { print("销毁 limited")}
)
//
//使用using操作符创建序列
// 当limited 销毁时,infiniteInterval同样销毁
let o: Observable<Int> = Observable.using({ () -> AnyDisposable in
return AnyDisposable(infiniteInterval.subscribe())
}, observableFactory: { _ in return limited})
o.subscribe().disposed(by: dis)