RxSwift学习之旅 - 序列的基本操作

合并操作

合并多个序列或者值成单个序列。

startWith

在序列触发值之前插入一个多个元素的特殊序列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let disposeBag = DisposeBag()

Observable.of("🐶", "🐱", "🐭", "🐹")
.startWith("1️⃣")
.startWith("2️⃣")
.startWith("3️⃣", "🅰️", "🅱️")
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
3️⃣
🅰️
🅱️
2️⃣
1️⃣
🐶
🐱
🐭
🐹

最后插入的元素数组在最前面,如下图:

image

merge

把多个序列合并成单个序列,并按照事件触发的先后顺序,依次发射值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
let disposeBag = DisposeBag()

let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()

Observable.of(subject1, subject2)
.merge()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

subject1.onNext("🅰️")

subject1.onNext("🅱️")

subject2.onNext("①")

subject2.onNext("②")

subject1.onNext("🆎")

subject2.onNext("③")

output:
🅰️
🅱️


🆎

如图:

image

当其中某个序列发生了错误就会立即把错误发送到合并的序列并终止。

zip

把多个序列组合成到一起并触发一个值,但只有每一个序列都发射了一个值之后才会组合成一个新的值并发出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let disposeBag = DisposeBag()

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("🅰️")
stringSubject.onNext("🅱️")

intSubject.onNext(1)

intSubject.onNext(2)

stringSubject.onNext("🆎")
intSubject.onNext(3)

output:
🅰️ 1
🅱️ 2
🆎 3

如图:

image

combineLatest

获取两个序列的最新值,并通过某个函数对其进行处理,处理完之后返回一个新的发射值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let disposeBag = DisposeBag()

let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()

Observable.combineLatest(stringSubject, intSubject) { stringElement, intElement in
"\(stringElement) \(intElement)"
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

stringSubject.onNext("🅰️")

stringSubject.onNext("🅱️")
intSubject.onNext(1)

intSubject.onNext(2)

stringSubject.onNext("🆎")

output:
🅱️ 1
🅱️ 2
🆎 2

如图:

image

combineLatest还有一个变体可以接受一个数组,或者任何其他可被观察序列的集合。但是要求这些可被观察序列元素是同一类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let disposeBag = DisposeBag()
let stringObservable = Observable.just("❤️")
let fruitObservable = Observable.from(["🍎", "🍐", "🍊"])
let animalObservable = Observable.of("🐶", "🐱", "🐭", "🐹")

Observable.combineLatest([stringObservable, fruitObservable, animalObservable]) {
"\($0[0]) \($0[1]) \($0[2])"
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
❤️ 🍎 🐶
❤️ 🍐 🐶
❤️ 🍐 🐱
❤️ 🍊 🐱
❤️ 🍊 🐭
❤️ 🍊 🐹

switchLatest

这个也是用来合并序列的,不过不同的是,每当一个新的序列发射时,原来序列将被丢弃。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
let disposeBag = DisposeBag()

let subject1 = BehaviorSubject(value: "⚽️")
let subject2 = BehaviorSubject(value: "🍎")

let variable = Variable(subject1)

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

subject1.onNext("🏈")
subject1.onNext("🏀")

variable.value = subject2 //这是发射了一个新的序列,而不是直接覆盖原来的序列

subject1.onNext("⚾️") //这里发射的值被忽略了

subject2.onNext("🍐")

output:
⚽️
🏈
🏀
🍎
🍐

大家想想把这里的switchLatest改成merge会输出什么?

图例:

image

sample

当收到目标事件,就会从源序列取一个最新的事件,发送到序列,如果两次目标事件之间没有源序列的事件,则不发射值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let source = PublishSubject<Int>()
let target = PublishSubject<String>()

let subscription = source
.sample(target)
.subscribe { event in
print(event)
}
source.onNext(1)
target.onNext("A") //获取最新的source
source.onNext(2)
source.onNext(3)
target.onNext("B") //获取最新的source
target.onNext("C") //没有最新的source,不发射

output:
next(1)
next(3)

转换操作

对当前序列的值进行转换发射一个新的序列。

map

Swift里面的map类似,转换其中的每一个元素。

1
2
3
4
5
6
7
8
9
10
let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
.map { $0 * $0 }
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
1
4
9

image

faltMap

把当前序列的元素转换成一个新的序列,并把他们合并成一个序列,这个在我们的一个可被观察者序列本身又会触发一个序列的时候非常有用,比如发送一个新的网络请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let disposeBag = DisposeBag()

struct Player {
var score: Variable<Int>
}

let 👦🏻 = Player(score: Variable(80))
let 👧🏼 = Player(score: Variable(90))

let player = Variable(👦🏻)

player.asObservable()
.flatMap { $0.score.asObservable() } // Change flatMap to flatMapLatest and observe change in printed output
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

👦🏻.score.value = 85

player.value = 👧🏼

👦🏻.score.value = 95 // Will be printed when using flatMap, but will not be printed when using flatMapLatest

👧🏼.score.value = 100

output:
80
85
90
95
100

image

flatMapLatest

faltMap不同的是,flatMapLatest在收到一个新的序列的时候,会丢弃原有的序列。那么我们把上面的代码里面的flatMap改成flatMapLatest会输出什么呢?

flatMapLatest相当于mapswitchLatest操作的组合。

scan

Swift里面的reduce类似,给予一个初始值,依次对每个元素进行操作,最后返回操作的结果。

1
2
3
4
5
6
7
8
9
10
11
12
13
let disposeBag = DisposeBag()

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

output:
11
111
1111

如图:

image

过滤和条件操作

filter

Swift里面的filter类似,用来过滤序列中指定条件的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let disposeBag = DisposeBag()

Observable.of(
"🐱", "🐰", "🐶",
"🐸", "🐱", "🐰",
"🐹", "🐸", "🐱")
.filter {
$0 == "🐱"
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
🐱
🐱
🐱

如图:

image

distinctUntilChanged

过滤掉连续发射的重复元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
let disposeBag = DisposeBag()

Observable.of("🐱", "🐷", "🐱", "🐱", "🐱", "🐵", "🐱")
.distinctUntilChanged()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
🐱
🐷
🐱
🐵
🐱

elementAt

只发送指定位置的值。

1
2
3
4
5
6
7
8
9
let disposeBag = DisposeBag()

Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.elementAt(3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
🐸

如图:

image

single

发送单个元素,或者满足条件的第一个元素,如果有多个元素或者没有元素都会抛出错误。

1
2
3
4
5
6
7
8
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.single()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
🐱
Received unhandled error: /var/folders/h3/8n169g610_g69k50z7g_q4gc0000gp/T/./lldb/77046/playground61.swift:69:__lldb_expr_61 -> Sequence contains more than one element.

如果这里只有一个元素,则不会报错。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.single { $0 == "🐸" }
.subscribe { print($0) }
.disposed(by: disposeBag)

Observable.of("🐱", "🐰", "🐶", "🐱", "🐰", "🐶")
.single { $0 == "🐰" }
.subscribe { print($0) }
.disposed(by: disposeBag)

Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.single { $0 == "🔵" }
.subscribe { print($0) }
.disposed(by: disposeBag)

output:
next(🐸)
completed
next(🐰)
error(Sequence contains more than one element.)
error(Sequence doesn't contain any elements.)

take

获取序列前多少个值。

1
2
3
4
5
6
7
8
9
10
11
12
let disposeBag = DisposeBag()

Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.take(3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)
}

output:
🐱
🐰
🐶

takeLast

获取序列后多少个值。

1
2
3
4
5
6
7
8
9
10
11
let disposeBag = DisposeBag()

Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.takeLast(3)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
🐸
🐷
🐵

takeWhile

发射值值到条件变成false,变成false后,后面满足条件的值也不会发射。

1
2
3
4
5
6
7
8
9
10
11
let disposeBag = DisposeBag()

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

output:
1
2
3

如果在4后面加了个1会输出什么?

如图:

image

takeUntil

发射原序列,直到新的序列发射了一个值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
let disposeBag = DisposeBag()

let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()

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

sourceSequence.onNext("🐱")
sourceSequence.onNext("🐰")
sourceSequence.onNext("🐶")

referenceSequence.onNext("🔴")

sourceSequence.onNext("🐸")
sourceSequence.onNext("🐷")
sourceSequence.onNext("🐵")

output:
next(🐱)
next(🐰)
next(🐶)
completed

如图:

image

skip

跳过开头指定个数的值。

1
2
3
4
5
6
7
8
9
10
11
12
let disposeBag = DisposeBag()

Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.skip(2)
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
🐶
🐸
🐷
🐵

如图:

image

skipWhile

跳过满足条件的值到条件变成false,变成false后,后面满足条件的值也不会跳过。

1
2
3
4
5
6
7
8
9
10
11
let disposeBag = DisposeBag()

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

output:
4
5
6

如果在4后面加了个1会输出什么?

如图:

image

skipWhileWithIndex

skipWhile类似,只不过带上了index

1
2
3
4
5
6
7
8
9
10
11
12
13
let disposeBag = DisposeBag()

Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.skipWhileWithIndex { element, index in
index < 3
}
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
🐸
🐷
🐵

skipUntil

takeUntil相反,跳过原序列,直到新序列发射了一个值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
let disposeBag = DisposeBag()

let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()

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

sourceSequence.onNext("🐱")
sourceSequence.onNext("🐰")
sourceSequence.onNext("🐶")

referenceSequence.onNext("🔴")

sourceSequence.onNext("🐸")
sourceSequence.onNext("🐷")
sourceSequence.onNext("🐵")

output:
🐸
🐷
🐵

如图:

image

聚合操作

toArray

把一个序列转成一个数组,然后作为新的一个值发射。

1
2
3
4
5
6
7
8
9
10
 let disposeBag = DisposeBag()

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

output:
next([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
completed

reduce

给一个初始值,然后和序列里的每个值进行运行,最后返回一个结果,然后把结果作为单个值发射出去。

1
2
3
4
5
6
7
8
9
let disposeBag = DisposeBag()

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

output:
1111

concat

串联多个序列,下一个序列必须等前一个序列完成才会发射出来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
let disposeBag = DisposeBag()

let subject1 = BehaviorSubject(value: "🍎")
let subject2 = BehaviorSubject(value: "🐶")

let variable = Variable(subject1)

variable.asObservable()
.concat()
.subscribe { print($0) }
.disposed(by: disposeBag)

subject1.onNext("🍐")
subject1.onNext("🍊")

variable.value = subject2

subject2.onNext("I would be ignored")
subject2.onNext("🐱")

subject1.onCompleted()

subject2.onNext("🐭")

output:
next(🍎)
next(🍐)
next(🍊)
next(🐱)
next(🐭)

如图:

image

大家想一想下面会输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()

let variable = Variable(subject1)

variable.asObservable()
.concat()
.subscribe { print($0) }
.disposed(by: disposeBag)

subject1.onNext("🍐")
subject1.onNext("🍊")

variable.value = subject2

subject2.onNext("I would be ignored")
subject2.onNext("🐱")

subject1.onCompleted()

subject2.onNext("🐭")

连接操作

可连接的序列和一般序列没有不同,除了只有当调用connect()之后才会开始发射值,通过这种方式,你可以等所有的订阅者订阅后才发射值。

先来看一个没有连接操作的例子:

1
2
3
4
5
6
7
8
9
let interval = Observable<Int>.interval(2, scheduler: MainScheduler.instance)

_ = interval
.subscribe(onNext: { print("Subscription: 1, Event: \($0)") })

delay(5) {
_ = interval
.subscribe(onNext: { print("Subscription: 2, Event: \($0)") })
}

第一行代码是在指定的线程每隔一定的时间发射一个信号。

那么这里我们可以看到在第一个订阅者订阅后,每隔2秒会收到一个值,而后面一个订阅5秒后才收到第一个值0,所以两个订阅者接收到的值是不同步的。

看输出:

1
2
3
4
5
6
7
8
9
Subscription: 1, Event: 0
Subscription: 1, Event: 1
Subscription: 1, Event: 2
Subscription: 2, Event: 0 //这里是从0开始的
Subscription: 1, Event: 3
Subscription: 2, Event: 1
Subscription: 1, Event: 4
Subscription: 2, Event: 2
.......

publish

把一个序列转成一个可连接的序列。

首先来看一个没有连接的序列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let intSequence = Observable<Int>.interval(2, scheduler: MainScheduler.instance)

_ = intSequence
.subscribe(onNext: { print("Subscription 1:, Event: \($0)") })

delay(4) {
_ = intSequence
.subscribe(onNext: { print("Subscription 2:, Event: \($0)") })
}

delay(5) {
_ = intSequence
.subscribe(onNext: { print("Subscription 3:, Event: \($0)") })
}

结果如下:

1
2
3
4
5
6
7
8
9
Subscription 1:, Event: 0     //第一个订阅者开始订阅
Subscription 1:, Event: 1
Subscription 1:, Event: 2
Subscription 2:, Event: 0 //第二个订阅者开始订阅,不过发射的是一个新的序列
Subscription 3:, Event: 0 //第三个订阅者开始订阅,不过发射的是一个新的序列
Subscription 1:, Event: 3
Subscription 2:, Event: 1
Subscription 3:, Event: 1
Subscription 1:, Event: 4

把第一行代码变成:

1
2
let intSequence = Observable<Int>.interval(2, scheduler: MainScheduler.instance)
.publish()

加了个publish后变成可连接序列了,但是并不会输出值,只有在调用connect之后才会开始发射值。而且与前面不同的是,前面的Observable被多次subscribe就会被多次触发。publish + connect的组合每次subscribe不会导致Observable重新针对observer处理一遍。

所以如果上面的代码写成这样会输出什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
let intSequence = Observable<Int>.interval(2, scheduler: MainScheduler.instance)
.publish()

print("1 订阅")

_ = intSequence
.subscribe(onNext: { print("Subscription 1:, Event: \($0)") })

delay(1) { _ = intSequence.connect() } //connect后,序列开始发射

delay(4) {
print("4 订阅")
_ = intSequence
.subscribe(onNext: { print("Subscription 2:, Event: \($0)") })
}

delay(5) {
print("5 订阅")
_ = intSequence
.subscribe(onNext: { print("Subscription 3:, Event: \($0)") })
}

output:
1 订阅
Subscription 1:, Event: 0 //1订阅,收到值
4 订阅
5 订阅
Subscription 1:, Event: 1 //4,5 订阅,收到的是原序列继续发射的值,而不是新的序列
Subscription 2:, Event: 1
Subscription 3:, Event: 1
Subscription 1:, Event: 2
Subscription 2:, Event: 2
Subscription 3:, Event: 2
Subscription 1:, Event: 3
Subscription 2:, Event: 3
Subscription 3:, Event: 3

如图:

image

replay

把源序列转换可连接的序列,并会给新的订阅者发送之前bufferSize个的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
let intSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.replay(5)
print("1 订阅")
_ = intSequence
.subscribe(onNext: { print("Subscription 1:, Event: \($0)") })

delay(1) { _ = intSequence.connect() }

delay(4) {
print("4 订阅")
_ = intSequence
.subscribe(onNext: { print("Subscription 2:, Event: \($0)") })
}

delay(5) {
print("5 订阅")
_ = intSequence
.subscribe(onNext: { print("Subscription 3:, Event: \($0)") })
}

output:
1 订阅
Subscription 1:, Event: 0
Subscription 1:, Event: 1
4 订阅
Subscription 2:, Event: 0
Subscription 2:, Event: 1 //之前发射的值
Subscription 1:, Event: 2
Subscription 2:, Event: 2
5 订阅
Subscription 3:, Event: 0
Subscription 3:, Event: 1
Subscription 3:, Event: 2 //之前发射的值
Subscription 1:, Event: 3
Subscription 2:, Event: 3
Subscription 3:, Event: 3

如图:

image

multicast

传入一个Subject,每当序列发射都会触发这个Subject的发射。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
let subject = PublishSubject<Int>()

_ = subject
.subscribe(onNext: { print("Subject: \($0)") })

let intSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.multicast(subject)

_ = intSequence
.subscribe(onNext: { print("\tSubscription 1:, Event: \($0)") })

delay(2) { _ = intSequence.connect() }

delay(4) {
_ = intSequence
.subscribe(onNext: { print("\tSubscription 2:, Event: \($0)") })
}

delay(6) {
_ = intSequence
.subscribe(onNext: { print("\tSubscription 3:, Event: \($0)") })
}

output:
Subject: 0
Subscription 1:, Event: 0
Subject: 1
Subscription 1:, Event: 1
Subscription 2:, Event: 1
Subject: 2
Subscription 1:, Event: 2
Subscription 2:, Event: 2
Subject: 3
Subscription 1:, Event: 3
Subscription 2:, Event: 3
Subscription 3:, Event: 3

错误操作

catchErrorJustReturn

捕获到错误的时候,返回指定的值,然后终止。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let disposeBag = DisposeBag()

let sequenceThatFails = PublishSubject<String>()

sequenceThatFails
.catchErrorJustReturn("😊")
.subscribe { print($0) }
.disposed(by: disposeBag)

sequenceThatFails.onNext("😬")
sequenceThatFails.onNext("😨")
sequenceThatFails.onNext("😡")
sequenceThatFails.onNext("🔴")
sequenceThatFails.onError(TestError.test)

output:
next(😬)
next(😨)
next(😡)
next(🔴)
next(😊)
completed

image

catchError

捕获一个错误值,然后切换到新的序列。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
let disposeBag = DisposeBag()  
let sequenceThatFails = PublishSubject<String>()
let recoverySequence = PublishSubject<String>()

sequenceThatFails
.catchError {
print("Error:", $0)
return recoverySequence
}
.subscribe { print($0) }
.disposed(by: disposeBag)

sequenceThatFails.onNext("😬")
sequenceThatFails.onNext("😨")
sequenceThatFails.onNext("😡")
sequenceThatFails.onNext("🔴")
sequenceThatFails.onError(TestError.test)

recoverySequence.onNext("😊")

output:
next(😬)
next(😨)
next(😡)
next(🔴)
Error: test
next(😊)

如图:

image

retry

捕获到错误的时候,重新订阅该序列。retry(_:) 表示最多重试多少次。 retry(3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
let disposeBag = DisposeBag()
var count = 1

let sequenceThatErrors = Observable<String>.create { observer in
observer.onNext("🍎")
observer.onNext("🍐")
observer.onNext("🍊")

if count == 1 {
observer.onError(TestError.test)
print("Error encountered")
count += 1
}

observer.onNext("🐶")
observer.onNext("🐱")
observer.onNext("🐭")
observer.onCompleted()

return Disposables.create()
}

sequenceThatErrors
.retry()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
🍎
🍐
🍊
Error encountered
🍎
🍐
🍊
🐶
🐱
🐭

如图:

image

调试操作

debug

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
let disposeBag = DisposeBag()
var count = 1

let sequenceThatErrors = Observable<String>.create { observer in
observer.onNext("🍎")
observer.onNext("🍐")
observer.onNext("🍊")

if count < 5 {
observer.onError(TestError.test)
print("Error encountered")
count += 1
}

observer.onNext("🐶")
observer.onNext("🐱")
observer.onNext("🐭")
observer.onCompleted()

return Disposables.create()
}

sequenceThatErrors
.retry(3)
.debug()
.subscribe(onNext: { print($0) })
.disposed(by: disposeBag)

output:
2017-03-25 12:38:47.241: playground157.swift:42 (__lldb_expr_157) -> subscribed
2017-03-25 12:38:47.246: playground157.swift:42 (__lldb_expr_157) -> Event next(🍎)
🍎
2017-03-25 12:38:47.247: playground157.swift:42 (__lldb_expr_157) -> Event next(🍐)
🍐
2017-03-25 12:38:47.248: playground157.swift:42 (__lldb_expr_157) -> Event next(🍊)
🍊
Error encountered
2017-03-25 12:38:47.250: playground157.swift:42 (__lldb_expr_157) -> Event next(🍎)
🍎
2017-03-25 12:38:47.250: playground157.swift:42 (__lldb_expr_157) -> Event next(🍐)
🍐
2017-03-25 12:38:47.251: playground157.swift:42 (__lldb_expr_157) -> Event next(🍊)
🍊
Error encountered
2017-03-25 12:38:47.252: playground157.swift:42 (__lldb_expr_157) -> Event next(🍎)
🍎
2017-03-25 12:38:47.253: playground157.swift:42 (__lldb_expr_157) -> Event next(🍐)
🍐
2017-03-25 12:38:47.253: playground157.swift:42 (__lldb_expr_157) -> Event next(🍊)
🍊
Error encountered
2017-03-25 12:38:47.255: playground157.swift:42 (__lldb_expr_157) -> Event error(test)
Received unhandled error: /var/folders/h3/8n169g610_g69k50z7g_q4gc0000gp/T/./lldb/26516/playground157.swift:43:__lldb_expr_157 -> test
2017-03-25 12:38:47.283: playground157.swift:42 (__lldb_expr_157) -> isDisposed

RxSwift.Resources.total

提供所有Rx申请资源的数量,在检查内存泄露的时候非常有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
print(RxSwift.Resources.total)

let disposeBag = DisposeBag()

print(RxSwift.Resources.total)

let variable = Variable("🍎")

let subscription1 = variable.asObservable().subscribe(onNext: { print($0) })

print(RxSwift.Resources.total)

let subscription2 = variable.asObservable().subscribe(onNext: { print($0) })

print(RxSwift.Resources.total)

subscription1.dispose()

print(RxSwift.Resources.total)

subscription2.dispose()

print(RxSwift.Resources.total)

output:
0
2
🍎
8
🍎
10
9
8

参考资料

RxSwift

Document

RxMarbles

AloneMonkey wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!