在这一节,我们来看如何选择序列中的特定事件。
elementAt
首先,是选择序列中的第n个事件。还是基于上一节的例子,如果我们要订阅第二个任务,就可以这样:
tasks.elementAt(1)
.subscribe {
print($0)
}
.addDisposableTo(bag)
执行一下,就可以看到结果了:
getting-ops-1要注意的是,elementAt
的参数和数组的索引一样,第一个任务的索引是0,而不是1。它的序列图,是这样的:
filter
除了用事件的索引来选择之外,我们也可以用一个closure设置选择事件的标准,这就是filter
的作用,它会选择序列中所有满足条件的元素。例如,我们订阅值是T2
的事件:
tasks.filter { $0 == "T2" }
.subscribe {
print($0)
}
.addDisposableTo(bag)
执行一下,就会发现,结果和刚才是一样的。这说明,filter
同时过滤掉了T1
和T3
,它会检查序列中的每一个事件。它的序列图,是这样的:
take
除了选择订阅单一事件之外,我们也可以选择一次性订阅多个事件,例如,选择序列中的前两个事件:
tasks.take(2)
.subscribe {
print($0)
}
.addDisposableTo(bag)
takeWhile / takeWhileWithIndex
或者,我们也可以用一个closure来指定“只要条件为true就一直订阅下去”这样的概念。例如,只要任务不是T3就一直订阅下去:
tasks.takeWhile {
$0 != "T3"
}
.subscribe {
print($0)
}
.addDisposableTo(bag)
我们会在控制台看到这样的结果:
getting-ops-1这看似很简单,但有时候,我们经常会对它的用法产生一些错觉。例如,错把订阅终止条件写在了takeWhile
参数里,就像这样:
// This following is WRONG
tasks.takeWhile {
$0 == "T3"
}
.subscribe {
print($0)
}
.addDisposableTo(bag)
上面的代码会得到什么结果呢?实际上只能订阅到.completed
。因为,当匹配到第一个事件的时候,"T1" == "T3"
是false
,所以订阅就结束了。有时,我们不仅希望约束订阅到的事件,还需要获得事件在序列中的位置。为此,RxSwift提供了一个功能和takeWhile
类似的operator,只是在它的closure里,可以同时访问到事件值和事件在队列中的索引,像这样:
tasks.takeWhileWithIndex { (value, index) in
value != "T3" && index < 1
}
.subscribe {
print($0)
}
.addDisposableTo(bag)
takeWhileWithIndex
的closure有两个参数,第一个是事件的值,第二个是事件在序列中的索引。它的语义和takeWhile
是完全一样的,需要注意的仍旧是,在closure里写的,是读取事件的条件,而不是终止读取的条件。
takeUntil
除了使用closure表示订阅条件之外,我们也可以依赖另外一个外部事件,表达“直到某件事件发生前,一直订阅”这样的语义。例如下面的例子:
example("ignoreElements") {
let tasks = PublishSubject<String>()
let bossHasGone = PublishSubject<Void>()
let bag = DisposeBag()
tasks.takeUntil(bossHasGone).subscribe {
print($0)
}
.addDisposableTo(bag)
tasks.onNext("T1")
tasks.onNext("T2")
tasks.onNext("T3")
tasks.onCompleted()
}
我们新添加了一个bossHasGone
,表示老板已经不在了的事件,尽管我们使用了takeUntil
operator,但bossHasGone
还没有任何事件发生,因此我们仍旧会订阅到所有事件。现在,在T2
和T3
之间,给bossHasGone
发送个事件:
tasks.onNext("T1")
tasks.onNext("T2")
bossHasGone.onNext()
tasks.onNext("T3")
tasks.onCompleted()
重新执行一下,就会看到,我们只能订阅到T1
和T2
了。
What's next?
以上,就是和订阅特定事件相关的operators。包括了订阅特定位置事件(elementAt
)、订阅指定个数事件(take
)到订阅满足特定条件事件(filter
/ takeWhile
/ takeUntil
)。它们和上一节中的所有忽略事件operators一起,在Rx世界里,统称为事件过滤类型的operators。在下一节,我们就通过一个真实的App,进一步了解这些operators的用法。
网友评论