嗨,我正在努力了解RxSwift库,以便编写更好的函数式代码。
目前我陷入了一个非常基本的问题。假设我得到了Variable<[CiteModel?]>
:类型的变量
var allCites: Variable<[CiteModel?]> = Variable([])
var shownCites: Variable<[CiteModel?]> = Variable([])
现在我想过滤allCites
数组中包含特定文本的所有引用,并将它们添加到shownCites
中。
这是我尝试过的,但它没有编译,因为在我的过滤器块$0
中是[CiteModel?]
,而不是我期望的CiteModel?
。你能向我解释一下我做错了什么吗?
private func filterCitesByQuery(query: String) {
self.shownCites = self.allCites.asObservable().filter {
$0?.cite.containsString(query)
}
}
执行上述代码时出错:
Cannot assign value of type 'Observable<[CiteModel?]>' (aka 'Observable<Array<Optional<CiteModel>>>') to type 'Variable<[CiteModel?]>' (aka 'Variable<Array<Optional<CiteModel>>>')
map
对序列的每个值执行一个运算。当将map
应用于Observable<T>
时,map
将接收T
作为其块的参数。
在Variable<[CiteModel?]>
的情况下,Observable
是序列,因此是T == [CiteModel?]
。
因为我们真的想过滤[CiteModel?]
的数组,所以可以将filterCitesByQuery
的定义更改为
private func filterCitesByQuery(query: String) {
// bag probably needs to be reset here
allCites.asObservable()
.map { // map: apply a transformation to $0
// The desired transformation of $0 is to remove cite that do not contain query
$0.filter { $0.cite.containsString(query) }
}
.bindTo(shownCites)
.addDisposableTo(bag)
}
但这个片段仍然是次优的,因为它需要订阅allCites
,而我们实际上并不想观察它的变化。
是更好的实现方式
var allCites: Variable<[CiteModel?]> = Variable([])
var searchQuery: Variable<String> = Variable("")
var shownCites: Observable<[CiteModel?]> = Observable .combineLatest(allCites.asObservable(), searchQuery.asObservable()) {
allCites, query in
return allCites.map { cites in cites.filter { $0.cite.containsString(query) } }
}
private func filterCitesByQuery(query: String) {
searchQuery.value = query
}
这是怎么回事?
CCD_ 18取CCD_ 19和CCD_。当其中任何一个发生变化时,该块将被执行。我们现在可以订阅shownCites
,并且每次源可观察到的任何一个变化时都会获得更新的值。
我使用了以下代码:
private func filterCitesByQuery(query: String) {
self.shownCites.value = self.allCites.value.filter {
return $0?.cite.containsString(query) ?? false
}
}
然而,我仍然想知道哪一个是错误的原始代码。因此,如果有人能给我一个答案,我将不胜感激。
//transform Variable to Observable
allCites.asObservable()
// Observable<[CiteModel?]> -> Observable<CiteModel?>
.flatMap { $0.toObservable() }
// $0?.containsString("query") is Optional, so I have to add ?? false.
.filter { $0?.containsString("query") ?? false }
// Observable<CiteModel?> -> Observable<[CiteModel?]>
.toArray()
// use bind (a.k.a. subscribe. Don't use .value of Variable)
.bindTo(shownCites)
.addDisposableTo(bag)
这段代码应该为您完成:)