Swift RxSwift(三)

介绍

为什么使用RxSwift?

我们写代码的时候,为了响应一些外面事件,需要写很多代码。当我们操作一个控件时,需要写@IBAction来相应控件。当手机中软键盘弹出的时候,需要监测键盘通知来观察键盘位置变化。当一个URL请求返回数据时,需要提供闭包的方式来处理回调。当我们使用KVO时,需要观察值的变化。

所有这些各种各样的,都会使我们的代码产生一些不必要的复杂。难道没有一个更好的框架,能够统一相应所有的这些事件和回调。RxSwift就是这样的一个框架。

RxSwift是一个正式履行Reactive X (aka Rx),Rx支持很多语言和平台,Rx可以说无处不在most major languages and platforms.

思想

每一个 Observable 实例都是一个序列

Observable可以理解为就是一个被观察的对象,是一个事件序列,可以订阅它,监测事件的发生(Next\Complete\Error)。

一个关键的优势Observable与Swift的SequenceType,它还可以异步接收元素。这就是RxSwif的本质,其他的也可以根据这一思想进行扩展。

  • 一个Observable (ObservableType)等同于SequenceType
  • The ObservableType.subscribe(_:) 的方法等同于SequenceType.generate()方法。
  • ObservableType.subscribe(_:)需要一个观察者(ObserverType),它将被订阅,用于接收事件和Observable发出的元素,而不是手动调用next()返回。

如果一个Observable发出一个next的事件Event.next(Element),它能继续发出更多的事件。然而,如果这个Observable发出另外一个错误事件Event.error(ErrorType或者发出一个完成事件Event.completed,这个Observable就不能发出额外事件给订阅者了。

序列的正则表达式:

next* (error | completed)?

解释:序列有大于等于0个元素情况;一旦接收到error或者completed事件,序列就不会在产生其他元素。

例子:

1
2
3
4
5
--1--2--3--4--5--6--|----> // "|" = Terminates normally
--a--b--c--d--e--f--X----> // "X" = Terminates with an error
--tap--tap----------tap--> // "|" = Continues indefinitely, such as a sequence of button taps

上面这些示意图称为弹子图(marble diagram),你可以在网站上看到很多类似的示意图RxMarbles.com.

Observables和observers

Observables可以理解为被订阅者订阅的事件,单词本意上是可被观察到的

observers可以理解观察者,订阅者subscribers,单词本意是观察者
Observables不会自己执行订阅,除非它有订阅者。下面是一个简单的例子,Observable用于不会执行回调,因为他没有订阅者。可以简单的理解为你订阅了报子,你没有订阅当然不会发报子。

1
2
3
4
5
6
7
8
example("Observable with no subscribers") {
_ = Observable<String>.create { observerOfString -> Disposable in
print("This will never be printed")
observerOfString.on(.next("😬"))
observerOfString.on(.completed)
return Disposables.create()
}
}

结果:

1
--- Observable with no subscribers example ---

在上面的例子中,如果被订阅了subscribe(_:),那么闭包就会执行。

1
2
3
4
5
6
7
8
9
10
11
example("Observable with subscriber") {
_ = Observable<String>.create { observerOfString in
print("Observable created")
observerOfString.on(.next("😉"))
observerOfString.on(.completed)
return Disposables.create()
}
.subscribe { event in
print(event)
}
}

结果:

1
2
3
4
--- Observable with subscriber example ---
Observable created
next(😉)
completed

注意:你不用关心Observables创建的细节,我们会在后面详细介绍。

注意:subscribe(_:)方法返回一个Disposable,代表一个可自由使用的资源,比如一个订阅subscription。这个Disposable在上面的例子中没有出现,被忽略了,但是在实际使用的时候,它应该被妥善的处理(释放资源)。通常的做法是把它添加到一个DisposeBag(和 autorelease pool 相似)。在之后所有的例子中你都应该加入妥善的处理,因为,嗯,熟能生巧🙂。你可以在Getting Started guide项目中的 Disposing section 中学习更多的关于这个处理的知识。

创建和订阅Observables

这里有以下几种方式创建和订阅Observable序列

never

创建一个不会终止也不会发出任何事件的序列Observable更多信息

1
2
3
4
5
6
7
8
9
example("empty") {
let disposeBag = DisposeBag()
Observable<Int>.empty()
.subscribe { event in
print(event)
}
.addDisposableTo(disposeBag)
}

结果:

1
--- never example ---

empty

创建一个只发出完成Completed事件的序列Observable更多信息

1
2
3
4
5
6
7
8
9
example("empty") {
let disposeBag = DisposeBag()
Observable<Int>.empty()
.subscribe { event in
print(event)
}
.addDisposableTo(disposeBag)
}

结果:

1
2
--- empty example ---
completed

just

创建一个仅有一个元素的序列Observable更多信息

1
2
3
4
5
6
7
8
9
example("just") {
let disposeBag = DisposeBag()
Observable.just("🔴")
.subscribe { event in
print(event)
}
.addDisposableTo(disposeBag)
}

结果:

1
2
3
--- just example ---
next(🔴)
completed

of

创建一个固定数量元素(参数)的序列Observable

1
2
3
4
5
6
7
8
9
example("of") {
let disposeBag = DisposeBag()
Observable.of("🐶", "🐱", "🐭", "🐹")
.subscribe(onNext: { element in
print(element)
})
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
--- of example ---
🐶
🐱
🐭
🐹

注意:这个例子还介绍了怎样使用subscribe(onNext:)便利方法。与subscribe(_:)不同的是,subscribe(_:)方法给所有的事件类型 (Next, Error, Completed) 订阅了一个event(事件)处理者,而subscribe(onNext:)方法则订阅了一个element(元素)处理者,这个element(元素)处理者将会忽略 ErrorCompleted 事件并且只产生 Next 事件元素。还有subscribe(onError:)subscribe(onCompleted:)便利方法,只要你想订阅这些事件类型。而且还有一个subscribe(onNext:onError:onCompleted:onDisposed:)方法,它允许你对一个或多个事件类型做出反应,而且在单独调用时当因为任何原因,或者被处理,订阅会被终止:

1
2
3
4
5
6
someObservable.subscribe(
onNext: { print("Element:", $0) },
onError: { print("Error:", $0) },
onCompleted: { print("Completed") },
onDisposed: { print("Disposed") }
)

from

使用一个SequenceType类型的对象创建一个Observable序列,比如一个ArrayDictionary,或者Set

1
2
3
4
5
6
7
example("from") {
let disposeBag = DisposeBag()
Observable.from(["🐶", "🐱", "🐭", "🐹"])
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
--- from example ---
🐶
🐱
🐭
🐹

注意:这个例子还演示了怎样使用默认参数名$0代替显示命名参数。

create

创建自定义的序列Observable更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
example("create") {
let disposeBag = DisposeBag()
let myJust = { (element: String) -> Observable<String> in
return Observable.create { observer in
observer.on(.next(element))
observer.on(.completed)
return Disposables.create()
}
}
myJust("🔴")
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}

结果:

1
2
3
--- create example ---
next(🔴)
completed

range

创建一个发出一系列连续的整数然后终止的序列Observable更多信息

1
2
3
4
5
6
7
example("range") {
let disposeBag = DisposeBag()
Observable.range(start: 1, count: 10)
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
6
7
8
9
10
11
12
--- range example ---
next(1)
next(2)
next(3)
next(4)
next(5)
next(6)
next(7)
next(8)
next(9)
next(10)
completed

repeatElement

创建一个不确定次数地发出制定元素的序列Observable,相当于重复元素。更多信息

1
2
3
4
5
6
7
8
example("repeatElement") {
let disposeBag = DisposeBag()
Observable.repeatElement("🔴")
.take(3)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- repeatElement example ---
🔴
🔴
🔴

注意:这个例子使用take操作,返回一个从序列开始到指定数字的元素数组。

generate

创建一个只满足条件true的序列Observable

1
2
3
4
5
6
7
8
9
10
11
example("generate") {
let disposeBag = DisposeBag()
Observable.generate(
initialState: 0,
condition: { $0 < 3 },
iterate: { $0 + 1 }
)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- generate example ---
0
1
2

deferred

为每一个订阅者创建一个序列Observable更多信息

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
example("deferred") {
let disposeBag = DisposeBag()
var count = 1
let deferredSequence = Observable<String>.deferred {
print("Creating \(count)")
count += 1
return Observable.create { observer in
print("Emitting...")
observer.onNext("🐶")
observer.onNext("🐱")
observer.onNext("🐵")
return Disposables.create()
}
}
deferredSequence
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
deferredSequence
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
6
7
8
9
10
11
--- deferred example ---
Creating 1
Emitting...
🐶
🐱
🐵
Creating 2
Emitting...
🐶
🐱
🐵

error

创建一个不发出任何事件并且遇见错误就会中断的序列Observable

1
2
3
4
5
6
7
example("error") {
let disposeBag = DisposeBag()
Observable<Int>.error(TestError.test)
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}

结果:

1
2
--- error example ---
error(test)

doOn

创建为每发出一个事情都调用一个附带动作并且返回原始事件。更多信息

1
2
3
4
5
6
7
8
example("doOn") {
let disposeBag = DisposeBag()
Observable.of("🍎", "🍐", "🍊", "🍋")
.do(onNext: { print("Intercepted:", $0) }, onError: { print("Intercepted error:", $0) }, onCompleted: { print("Completed") })
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
6
7
8
9
10
--- doOn example ---
Intercepted: 🍎
🍎
Intercepted: 🍐
🍐
Intercepted: 🍊
🍊
Intercepted: 🍋
🍋
Completed

注意:这里还有doOnNext(_:),doOnError(_:),和doOnCompleted(_:)拦截特定事件的便利方法,而且doOn(onNext:onError:onCompleted)方法在单独调用时可以拦截一个或多个事件。

Working with Subjects

一个Subject是一个桥梁或者代理,它可以在Rx中实现,扮演着观察者observerObservable的双重身份。因为它作为一个观察者observer,所以它能否订阅一个或者更多Observable,又因为它作为Observable,所以它能够回收它自己观察的事物,也能够发出新的事物。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
extension ObservableType {
/**
Add observer with `id` and print each emitted event.
- parameter id: an identifier for the subscription.
*/
func addObserver(_ id: String) -> Disposable {
return subscribe { print("Subscription:", id, "Event:", $0) }
}
}
func writeSequenceToConsole<O: ObservableType>(name: String, sequence: O) -> Disposable {
return sequence.subscribe { event in
print("Subscription: \(name), event: \(event)")
}
}

PublishSubject

对所有观察者observers订阅之后广播新事件,简单的说,就是订阅之后才发出事件给你。

1
2
3
4
5
6
7
8
9
10
11
12
example("PublishSubject") {
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
}

结果:

1
2
3
4
5
6
7
--- PublishSubject example ---
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)

注意: 这里使用onNext(_:)方法,这个方法相当于on(.next(_:))方法,这两个方法会导致一个提供element的新事件被发散到订阅者们上。还有onError(_:)onCompleted()便利方法,分别相当于on(.error(_:))方法和on(.completed)方法。

ReplaySubject

对所有订阅者广播新事件,并且可以把之前的事件,以指定好的BufferSize数量的事件发给最新新订阅者。简单的说,如果BufferSize为1,在你订阅这个事件的时候,会把订阅前的上一个事件也发给你。

1
2
3
4
5
6
7
8
9
10
11
12
example("ReplaySubject") {
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 1)
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
}

结果:

1
2
3
4
5
6
7
8
--- ReplaySubject example ---
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)

BehaviorSubject

对所有订阅者广播新事件,并且首先发出最近一个或者最初的一个事件给新的订阅者。简单的说,如果你是第一个订阅者,发出事情前会发一个默认的事件给你。如果你不是第一个订阅者,并且订阅前有事件发生,那么在你订阅的时候,会发生订阅前最后一次事件给你,然后发送订阅之后的事件给你。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
example("BehaviorSubject") {
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "🔴")
subject.addObserver("1").addDisposableTo(disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.addObserver("2").addDisposableTo(disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
subject.addObserver("3").addDisposableTo(disposeBag)
subject.onNext("🍐")
subject.onNext("🍊")
}

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
--- BehaviorSubject example ---
Subscription: 1 Event: next(🔴)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
Subscription: 3 Event: next(🅱️)
Subscription: 1 Event: next(🍐)
Subscription: 3 Event: next(🍐)
Subscription: 2 Event: next(🍐)
Subscription: 1 Event: next(🍊)
Subscription: 3 Event: next(🍊)
Subscription: 2 Event: next(🍊)

注意:前面这些例子中少了些什么吗?一个Completed事件。当PublishSubjectReplaySubjectBehaviorSubject即将被处理的时候,它们不会自动发出 Completed事件。

Variable

Variable其实是对BehaviorSubject的封装,并且Variable会维护当前的状态,Variable从不发送错误事件,但是,在deinit它会自动发送完成事件并且终止。

1
2
3
4
5
6
7
8
9
10
11
12
example("Variable") {
let disposeBag = DisposeBag()
let variable = Variable("🔴")
variable.asObservable().addObserver("1").addDisposableTo(disposeBag)
variable.value = "🐶"
variable.value = "🐱"
variable.asObservable().addObserver("2").addDisposableTo(disposeBag)
variable.value = "🅰️"
variable.value = "🅱️"
}

结果:

1
2
3
4
5
6
7
8
9
10
11
--- Variable example ---
Subscription: 1 Event: next(🔴)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
Subscription: 1 Event: completed
Subscription: 2 Event: completed

Variable调用asObservable()是为了访问BehaviorSubject序列的底层。Variable不会实现on操作(或者 onNext(_:)),而是暴露一个当前用到的值value的属性,也可以设置一个新值。设置一个新值当然也会作用到BehaviorSubject序列的底层中。

Combination Operators

组合多个Observables变成一个Observable的操作

startWith

在从Observable发送元素之前发送一些特别的元素。更多信息

1
2
3
4
5
6
7
8
9
10
example("startWith") {
let disposeBag = DisposeBag()
Observable.of("🐶", "🐱", "🐭", "🐹")
.startWith("1️⃣")
.startWith("2️⃣")
.startWith("3️⃣", "🅰️", "🅱️")
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
6
7
8
9
10
--- startWith example ---
3️⃣
🅰️
🅱️
2️⃣
1️⃣
🐶
🐱
🐭
🐹

注意:正如上面的例子,startWith遵循后进先出last-in-first-out的原则,也就是说,最后一个startWith最先出来。

merge

组合多个Observables合并成一个Observable,并且会发送每一个元素,实际上这些元素还是来自于它们原始的Observable更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
example("merge") {
let disposeBag = DisposeBag()
let subject1 = PublishSubject<String>()
let subject2 = PublishSubject<String>()
Observable.of(subject1, subject2)
.merge()
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
subject1.onNext("🅰️")
subject1.onNext("🅱️")
subject2.onNext("①")
subject2.onNext("②")
subject1.onNext("🆎")
subject2.onNext("③")
}

结果:

1
2
3
4
5
6
7
--- merge example ---
🅰️
🅱️
🆎

zip

将8个Observable序列组合成一个Observable,并从组合序列发送元素,根据这些元素的Observable的索引。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
example("zip") {
let disposeBag = DisposeBag()
let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()
Observable.zip(stringSubject, intSubject) { stringElement, intElement in
"\(stringElement) \(intElement)"
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
stringSubject.onNext("🅰️")
stringSubject.onNext("🅱️")
intSubject.onNext(1)
intSubject.onNext(2)
stringSubject.onNext("🆎")
intSubject.onNext(3)
}

结果:

1
2
3
4
--- zip example ---
🅰️ 1
🅱️ 2
🆎 3

combineLatest

将8个Observable组合成一个新的Observable序列,并且一旦所有源序列发出至少一个元素以及当任何源Observable序列发出一个新的元素的时候,将开始发出组合的Observable序列的最新的元素。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
example("combineLatest") {
let disposeBag = DisposeBag()
let stringSubject = PublishSubject<String>()
let intSubject = PublishSubject<Int>()
Observable.combineLatest(stringSubject, intSubject) { stringElement, intElement in
"\(stringElement) \(intElement)"
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
stringSubject.onNext("🅰️")
stringSubject.onNext("🅱️")
intSubject.onNext(1)
intSubject.onNext(2)
stringSubject.onNext("🆎")
}

结果:

1
2
3
4
--- combineLatest example ---
🅱️ 1
🅱️ 2
🆎 2

combineLatest同样可以在数组Array上面进行扩展extension

1
2
3
4
5
6
7
8
9
10
11
12
13
example("Array.combineLatest") {
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) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
6
7
--- Array.combineLatest example ---
❤️ 🍎 🐶
❤️ 🍐 🐶
❤️ 🍐 🐱
❤️ 🍊 🐱
❤️ 🍊 🐭
❤️ 🍊 🐹

注意:Array之上的combineLatest扩展要求所有源Observable序列的类型是相同的。

switchLatest

通过一个在Observable序列队里的Observable序列发出转换元素,并且发出最近的Observable序列里的元素。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
example("switchLatest") {
let disposeBag = DisposeBag()
let subject1 = BehaviorSubject(value: "⚽️")
let subject2 = BehaviorSubject(value: "🍎")
let variable = Variable(subject1)
variable.asObservable()
.switchLatest()
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
subject1.onNext("🏈")
subject1.onNext("🏀")
variable.value = subject2
subject1.onNext("⚾️")
subject2.onNext("🍐")
}

结果:

1
2
3
4
5
6
--- switchLatest example ---
⚽️
🏈
🏀
🍎
🍐

在这个例子中,在把variable.value赋值为subject2之后,在subject1中添加🏐没有意义,因为只有最近的内在Observable序列 (subject2) 将会发出元素。

Transforming Operators

可以转换Observable发送Next事件中元素的操作。

map

应用一个转换闭包于Observable发出的元素,并且返回一个新的转换过元素的Observable更多信息

1
2
3
4
5
6
7
example("map") {
let disposeBag = DisposeBag()
Observable.of(1, 2, 3)
.map { $0 * $0 }
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- map example ---
1 //1*1
4 //2*2
9 //3*3

flatMap and flatMapLatest

通过Observable发出的元素转换成Observable序列队,并且合并这些发散元素作为一个单独的Observable序列。有时候这是非常有用的,比如,当你有一个Observable序列本身能自己发出Observable序列,而且你希望能够响应新的发出Observable序列。flatMapflatMapLatest不同的是,flatMapLatest只会发出最新的内部Observable序列的元素。了解更多

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
example("flatMap and flatMapLatest") {
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) })
.addDisposableTo(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
}

结果:

1
2
3
4
5
6
--- flatMap and flatMapLatest example ---
80
85
90
95
100

在这个例子中,用flatMap可能产生意想不到的结果,在把👧赋值给player.value之后,👧.score将开始发出元素,但是在前面Observable序列之内也将一直发出元素。通过把flatMap改变成flatMapLatest,只有最新的Observable序列之内将发出元素,也就是说,设置 👦.score.value = 95是无效的。

flatMapLatest实际上是mapswitchLatest的组合。

scan

首先初始化一个值,然后把Observable序列发出的每个元素应用于一个累加器闭包中,并返回每个中间结果作为一个含有单个元素的Observable序列。更多信息

1
2
3
4
5
6
7
8
9
10
example("scan") {
let disposeBag = DisposeBag()
Observable.of(10, 100, 1000)
.scan(1) { aggregateValue, newValue in
aggregateValue + newValue
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- scan example ---
11
111
1111

Filtering and Conditional Operators

过滤和条件操作,有选择的从Observable发出元素的操作。

filter

发送仅满足指定条件的哪些元素。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
example("filter") {
let disposeBag = DisposeBag()
Observable.of(
"🐱", "🐰", "🐶",
"🐸", "🐱", "🐰",
"🐹", "🐸", "🐱")
.filter {
$0 == "🐱"
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- filter example ---
🐱
🐱
🐱

distinctUntilChanged

过滤掉Observable发出元素中相邻重复的元素。更多信息

1
2
3
4
5
6
7
8
example("distinctUntilChanged") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐷", "🐱", "🐱", "🐱", "🐵", "🐱")
.distinctUntilChanged()
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
6
--- distinctUntilChanged example ---
🐱
🐷
🐱
🐵
🐱

elementAt

只发送Observable中指定索引的元素。更多信息

1
2
3
4
5
6
7
8
example("elementAt") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.elementAt(3)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
--- elementAt example ---
🐸

single

发出Observable中的第一个元素(或者满足条件的第一个元素)。如果这个Observable不能发出一个元素或者根据条件查找到两个以上的元素将会抛出一个错误。顾名思义单一

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
example("single") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.single()
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}
example("single with conditions") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.single { $0 == "🐸" }
.subscribe { print($0) }
.addDisposableTo(disposeBag)
Observable.of("🐱", "🐰", "🐶", "🐱", "🐰", "🐶")
.single { $0 == "🐰" }
.subscribe { print($0) }
.addDisposableTo(disposeBag)
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.single { $0 == "🔵" }
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
6
7
8
9
10
--- single example ---
🐱
Received unhandled error: /var/folders/tr/g4phkfhs50324y0b15wlldhw0000gn/T/./lldb/5118/playground23.swift:69:__lldb_expr_23 -> Sequence contains more than one element.
--- single with conditions example ---
next(🐸)
completed
next(🐰)
error(Sequence contains more than one element.)
error(Sequence doesn't contain any elements.)

take

从开始计算,Observable发出指定数量的元素。更多信息

1
2
3
4
5
6
7
8
example("take") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.take(3)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- take example ---
🐱
🐰
🐶

takeLast

从结尾计算,Observable发出指定数量的元素。更多信息

1
2
3
4
5
6
7
8
example("takeLast") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.takeLast(3)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- takeLast example ---
🐸
🐷
🐵

takeWhile

Observable发出指定条件的元素。更多信息

1
2
3
4
5
6
7
8
example("takeWhile") {
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6)
.takeWhile { $0 < 4 }
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- takeWhile example ---
1
2
3

takeUntil

Observable中发出元素直到一个参照Observable发出一个元素。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
example("takeUntil") {
let disposeBag = DisposeBag()
let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()
sourceSequence
.takeUntil(referenceSequence)
.subscribe { print($0) }
.addDisposableTo(disposeBag)
sourceSequence.onNext("🐱")
sourceSequence.onNext("🐰")
sourceSequence.onNext("🐶")
referenceSequence.onNext("🔴")
sourceSequence.onNext("🐸")
sourceSequence.onNext("🐷")
sourceSequence.onNext("🐵")
}

结果:

1
2
3
4
5
--- takeUntil example ---
next(🐱)
next(🐰)
next(🐶)
completed

skip

Observable序列的开始发送元素,并且跳过指定数量的元素。更多信息

1
2
3
4
5
6
7
8
example("skip") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.skip(2)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
--- skip example ---
🐶
🐸
🐷
🐵

skipWhile

Observable开始发散元素,并且跳过满足条件的元素。更多信息

1
2
3
4
5
6
7
8
example("skipWhile") {
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6)
.skipWhile { $0 < 4 }
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- skipWhile example ---
4
5
6

skipWhileWithIndex

从一个源Observable序列的开始发散元素,并且跳过满足条件的索引的元素。这个闭包查询了每个元素。

1
2
3
4
5
6
7
8
9
10
example("skipWhileWithIndex") {
let disposeBag = DisposeBag()
Observable.of("🐱", "🐰", "🐶", "🐸", "🐷", "🐵")
.skipWhileWithIndex { element, index in
index < 3
}
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
--- skipWhileWithIndex example ---
🐸
🐷
🐵

skipUntil

跳过Observable发送的元素,直到一个参照Observable序列发出一个元素。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
example("skipUntil") {
let disposeBag = DisposeBag()
let sourceSequence = PublishSubject<String>()
let referenceSequence = PublishSubject<String>()
sourceSequence
.skipUntil(referenceSequence)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
sourceSequence.onNext("🐱")
sourceSequence.onNext("🐰")
sourceSequence.onNext("🐶")
referenceSequence.onNext("🔴")
sourceSequence.onNext("🐸")
sourceSequence.onNext("🐷")
sourceSequence.onNext("🐵")
}

结果:

1
2
3
4
--- skipUntil example ---
🐸
🐷
🐵

Mathematical and Aggregate Operators

数学和集合操作,通过Observable操作整个序列的元素的操作。

toArray

转换一个Observable为一个数组,这个数组作为一个新的单一元素Observable序列发送,然后终止。更多信息

1
2
3
4
5
6
7
8
example("toArray") {
let disposeBag = DisposeBag()
Observable.range(start: 1, count: 10)
.toArray()
.subscribe { print($0) }
.addDisposableTo(disposeBag)
}

结果:

1
2
3
--- toArray example ---
next([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
completed

reduce

初始化一个值,然后应用到一个累加器闭包作为所有Observable发出的元素回调,并且返回一个集合结果。相当于是一个累加器的操作。更多信息

1
2
3
4
5
6
7
8
example("reduce") {
let disposeBag = DisposeBag()
Observable.of(10, 100, 1000)
.reduce(1, accumulator: +)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
--- reduce example ---
1111

concat

以连续的方式,合并Observable序列队内部中的一个Observable序列的元素,在下一个序列发送元素之前等待每个序列成功终止。意思就是如果有很多个序列,必须等一个Observable序列发送的元素完成之后才进行下一个Observable序列发送元素。更多信息

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
example("concat") {
let disposeBag = DisposeBag()
let subject1 = BehaviorSubject(value: "🍎")
let subject2 = BehaviorSubject(value: "🐶")
let variable = Variable(subject1)
variable.asObservable()
.concat()
.subscribe { print($0) }
.addDisposableTo(disposeBag)
subject1.onNext("🍐")
subject1.onNext("🍊")
variable.value = subject2
subject2.onNext("I would be ignored")
subject2.onNext("🐱")
subject1.onCompleted()
subject2.onNext("🐭")
}

结果:

1
2
3
4
5
6
--- concat example ---
next(🍎)
next(🍐)
next(🍊)
next(🐱)
next(🐭)

Connectable Operators

可连接的操作,可连接的Observable类似于普通序列,除了它们被订阅的时候一开始是不发送元素的,只有当它们调用connect()的时候才发送,这样,我们可以等到所有订阅者们都准备好了,才发送元素。

注意:在下面的列子中,取消注释sampleWithoutConnectableOperators()是开始运行,开启注释是停止运行。

在学习可连接的Observable序列之前,让我们看一个不是可连接的操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func sampleWithoutConnectableOperators() {
printExampleHeader(#function)
let interval = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
_ = interval
.subscribe(onNext: { print("Subscription: 1, Event: \($0)") })
delay(5) {
_ = interval
.subscribe(onNext: { print("Subscription: 2, Event: \($0)") })
}
}
sampleWithoutConnectableOperators() // ⚠️ Uncomment to run this example; comment to stop running

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
--- sampleWithoutConnectableOperators() example ---
Subscription: 1, Event: 0
Subscription: 1, Event: 1
Subscription: 1, Event: 2
Subscription: 1, Event: 3
Subscription: 1, Event: 4
Subscription: 1, Event: 5
Subscription: 2, Event: 0
Subscription: 1, Event: 6
Subscription: 2, Event: 1
Subscription: 1, Event: 7
Subscription: 2, Event: 2
Subscription: 1, Event: 8
Subscription: 2, Event: 3
Subscription: 1, Event: 9
Subscription: 2, Event: 4
Subscription: 1, Event: 10
Subscription: 2, Event: 5
Subscription: 1, Event: 11
Subscription: 2, Event: 6

这里相当于timer,interval(间隔)创建一个Observable序列并且在每个period(周期)之后发散元素。更多信息

publish

Observable变成一个可连接的序列。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func sampleWithPublish() {
printExampleHeader(#function)
let intSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.publish()
_ = intSequence
.subscribe(onNext: { print("Subscription 1:, Event: \($0)") })
delay(2) { _ = intSequence.connect() }
delay(4) {
_ = intSequence
.subscribe(onNext: { print("Subscription 2:, Event: \($0)") })
}
delay(6) {
_ = intSequence
.subscribe(onNext: { print("Subscription 3:, Event: \($0)") })
}
}
//sampleWithPublish() // ⚠️ Uncomment to run this example; comment to stop running

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
--- sampleWithPublish() example ---
Subscription 1:, Event: 0
Subscription 1:, Event: 1
Subscription 2:, Event: 1
Subscription 1:, Event: 2
Subscription 2:, Event: 2
Subscription 1:, Event: 3
Subscription 3:, Event: 3
Subscription 2:, Event: 3
Subscription 1:, Event: 4
Subscription 3:, Event: 4
Subscription 2:, Event: 4
Subscription 1:, Event: 5
Subscription 3:, Event: 5
Subscription 2:, Event: 5
Subscription 1:, Event: 6
Subscription 3:, Event: 6
Subscription 2:, Event: 6
Subscription 1:, Event: 7
Subscription 3:, Event: 7
Subscription 2:, Event: 7

注意:调度程序作为一个抽象机制来执行工作,比如在特定线程或调度队列。更多信息

replay

Observable变成一个可连接的序列,并且重复发送bufferSize次。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func sampleWithReplayBuffer() {
printExampleHeader(#function)
let intSequence = Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.replay(5)
_ = intSequence
.subscribe(onNext: { print("Subscription 1:, Event: \($0)") })
delay(2) { _ = intSequence.connect() }
delay(4) {
_ = intSequence
.subscribe(onNext: { print("Subscription 2:, Event: \($0)") })
}
delay(8) {
_ = intSequence
.subscribe(onNext: { print("Subscription 3:, Event: \($0)") })
}
}
// sampleWithReplayBuffer() // ⚠️ Uncomment to run this example; comment to stop running

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
--- sampleWithReplayBuffer() example ---
Subscription 1:, Event: 0
Subscription 2:, Event: 0
Subscription 1:, Event: 1
Subscription 2:, Event: 1
Subscription 1:, Event: 2
Subscription 2:, Event: 2
Subscription 1:, Event: 3
Subscription 2:, Event: 3
Subscription 1:, Event: 4
Subscription 2:, Event: 4
Subscription 3:, Event: 0
Subscription 3:, Event: 1
Subscription 3:, Event: 2
Subscription 3:, Event: 3
Subscription 3:, Event: 4
Subscription 1:, Event: 5
Subscription 3:, Event: 5
Subscription 2:, Event: 5

multicast

Observable变成一个可连接的序列,并通过指定的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
func sampleWithMulticast() {
printExampleHeader(#function)
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)") })
}
}
//sampleWithMulticast() // ⚠️ Uncomment to run this example; comment to stop running

结果:

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
--- sampleWithMulticast() example ---
Subject: 0
Subscription 1:, Event: 0
Subject: 1
Subscription 2:, Event: 1
Subscription 1:, Event: 1
Subject: 2
Subscription 2:, Event: 2
Subscription 1:, Event: 2
Subject: 3
Subscription 2:, Event: 3
Subscription 3:, Event: 3
Subscription 1:, Event: 3
Subject: 4
Subscription 2:, Event: 4
Subscription 3:, Event: 4
Subscription 1:, Event: 4
Subject: 5
Subscription 2:, Event: 5
Subscription 3:, Event: 5
Subscription 1:, Event: 5
Subject: 6
Subscription 2:, Event: 6
Subscription 3:, Event: 6
Subscription 1:, Event: 6
Subject: 7
Subscription 2:, Event: 7
Subscription 3:, Event: 7
Subscription 1:, Event: 7

Error Handling Operators

错误处理操作该操作帮助重新覆盖来自Observable的错误通知。

catchErrorJustReturn

通过返回一个发送单独元素随后终止的Observable序列来重新覆盖一个Error事件。意识就是处理一些错误事件,返回自己特定的事件。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
example("catchErrorJustReturn") {
let disposeBag = DisposeBag()
let sequenceThatFails = PublishSubject<String>()
sequenceThatFails
.catchErrorJustReturn("😊")
.subscribe { print($0) }
.addDisposableTo(disposeBag)
sequenceThatFails.onNext("😬")
sequenceThatFails.onNext("😨")
sequenceThatFails.onNext("😡")
sequenceThatFails.onNext("🔴")
sequenceThatFails.onError(TestError.test)
}

结果:

1
2
3
4
5
6
7
--- catchErrorJustReturn example ---
next(😬)
next(😨)
next(😡)
next(🔴)
next(😊)
completed

catchError

重新覆盖通过切换被提供重新覆盖能力的Observable序列的Error事件。跟catchErrorJustReturn比较就是只抓取错误,不返回制定的值覆盖,并继续走下面的逻辑。更多信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
example("catchError") {
let disposeBag = DisposeBag()
let sequenceThatFails = PublishSubject<String>()
let recoverySequence = PublishSubject<String>()
sequenceThatFails
.catchError {
print("Error:", $0)
return recoverySequence
}
.subscribe { print($0) }
.addDisposableTo(disposeBag)
sequenceThatFails.onNext("😬")
sequenceThatFails.onNext("😨")
sequenceThatFails.onNext("😡")
sequenceThatFails.onNext("🔴")
sequenceThatFails.onError(TestError.test)
recoverySequence.onNext("😊")
}

结果:

1
2
3
4
5
6
7
--- catchError example ---
next(😬)
next(😨)
next(😡)
next(🔴)
Error: test
next(😊)

retry

屡次地重新覆盖通过重新订阅Observable序列的 Error 事件,不确定的。更多信息

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
example("retry") {
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) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
6
7
8
9
10
11
--- retry example ---
🍎
🍐
🍊
Error encountered
🍎
🍐
🍊
🐶
🐱
🐭

retry(_:)

屡次地重新覆盖通过重新订阅Observable序列的 Error 事件,直到达到maxAttemptCount的次数。

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
example("retry maxAttemptCount") {
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)
.subscribe(onNext: { print($0) })
.addDisposableTo(disposeBag)
}

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
--- retry maxAttemptCount example ---
🍎
🍐
🍊
Error encountered
🍎
🍐
🍊
Error encountered
🍎
🍐
🍊
Error encountered
Received unhandled error: /var/folders/tr/g4phkfhs50324y0b15wlldhw0000gn/T/./lldb/5118/playground85.swift:127:__lldb_expr_85 -> test

Debugging Operators

调试操作该类操作帮助调试 Rx 代码。

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
example("debug") {
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) })
.addDisposableTo(disposeBag)
}

结果:

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
--- debug example ---
2016-12-01 10:53:09.225: playground93.swift:42 (__lldb_expr_93) -> subscribed
2016-12-01 10:53:09.227: playground93.swift:42 (__lldb_expr_93) -> Event next(🍎)
🍎
2016-12-01 10:53:09.228: playground93.swift:42 (__lldb_expr_93) -> Event next(🍐)
🍐
2016-12-01 10:53:09.228: playground93.swift:42 (__lldb_expr_93) -> Event next(🍊)
🍊
Error encountered
2016-12-01 10:53:09.230: playground93.swift:42 (__lldb_expr_93) -> Event next(🍎)
🍎
2016-12-01 10:53:09.230: playground93.swift:42 (__lldb_expr_93) -> Event next(🍐)
🍐
2016-12-01 10:53:09.230: playground93.swift:42 (__lldb_expr_93) -> Event next(🍊)
🍊
Error encountered
2016-12-01 10:53:09.232: playground93.swift:42 (__lldb_expr_93) -> Event next(🍎)
🍎
2016-12-01 10:53:09.232: playground93.swift:42 (__lldb_expr_93) -> Event next(🍐)
🍐
2016-12-01 10:53:09.232: playground93.swift:42 (__lldb_expr_93) -> Event next(🍊)
🍊
Error encountered
2016-12-01 10:53:09.234: playground93.swift:42 (__lldb_expr_93) -> Event error(test)
Received unhandled error: /var/folders/tr/g4phkfhs50324y0b15wlldhw0000gn/T/./lldb/5118/playground93.swift:43:__lldb_expr_93 -> test
2016-12-01 10:53:09.234: playground93.swift:42 (__lldb_expr_93) -> 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
#if NOT_IN_PLAYGROUND
#else
example("RxSwift.Resources.total") {
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)
}
print(RxSwift.Resources.total)
#endif

结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
--- RxSwift.Resources.total example ---
0
1
🍎
4
🍎
6
5
4
0
Dec 1 10:53:11 [10671] <Error>: CGContextSetFillColorWithColor: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Dec 1 10:53:11 [10671] <Error>: CGContextSetStrokeColorWithColor: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Dec 1 10:53:11 [10671] <Error>: CGContextGetCompositeOperation: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Dec 1 10:53:11 [10671] <Error>: CGContextSetCompositeOperation: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Dec 1 10:53:11 [10671] <Error>: CGContextFillRects: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.
Dec 1 10:53:11 [10671] <Error>: CGContextSetCompositeOperation: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

注意:RxSwift.resourceCount在默认情况下不启用,通常不会启用发布构建。下面是展示如何启用它:

CocoaPods

1
2
3
4
5
6
7
8
9
10
11
12
13
14
target 'AppTarget' do
pod 'RxSwift'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == 'RxSwift'
target.build_configurations.each do |config|
if config.name == 'Debug'
config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['-D', 'TRACE_RESOURCES']
end
end
end
end
end

>

Carthage

  1. Run carthage build --configuration Debug.
  2. Build project (ProductBuild).