RxSwift 过滤器变量数组

RxSwift filter Variable array

您好,我正在尝试了解 RxSwift 库以编写更好的功能代码。

目前我被困在一个非常基本的问题上。可以说我得到了 Variable<[CiteModel?]>:

类型的变量
var allCites: Variable<[CiteModel?]> = Variable([])
var shownCites: Variable<[CiteModel?]> = Variable([])

现在我想从 allCites 数组中过滤所有包含特定文本的引用,并将它们添加到 shownCites

这是我尝试过的方法,但它无法编译,因为在我的过滤器块中 [=16=][CiteModel?] 而不是 CiteModel?会期待。你能解释一下我做错了什么吗?

private func filterCitesByQuery(query: String) {
    self.shownCites = self.allCites.asObservable().filter {
        [=11=]?.cite.containsString(query)
    }
}

执行上述代码时出错

Cannot assign value of type 'Observable<[CiteModel?]>' (aka 'Observable<Array<Optional<CiteModel>>>') to type 'Variable<[CiteModel?]>' (aka 'Variable<Array<Optional<CiteModel>>>')

我用这段代码得到了它:

private func filterCitesByQuery(query: String) {
     self.shownCites.value = self.allCites.value.filter {
         return [=10=]?.cite.containsString(query) ?? false
     }
 }

不过我还是想知道原代码哪里出了问题。因此,如果有人能为我解答,我将不胜感激。

    //transform Variable to Observable
    allCites.asObservable()
        // Observable<[CiteModel?]> -> Observable<CiteModel?>
        .flatMap { [=10=].toObservable() }
        // [=10=]?.containsString("query") is Optional, so I have to add ?? false.
        .filter { [=10=]?.containsString("query") ?? false }
        // Observable<CiteModel?> -> Observable<[CiteModel?]>
        .toArray()
        // use bind (a.k.a. subscribe. Don't use .value of Variable)
        .bindTo(shownCites)
        .addDisposableTo(bag)

这段代码应该可以为您完成:)

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 [=10=]
        // The desired transformation of [=10=] is to remove cite that do not contain query 
        [=10=].filter { [=10=].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 { [=11=].cite.containsString(query) } }
}

private func filterCitesByQuery(query: String) {
    searchQuery.value = query
}

这是怎么回事?

combineLatestallCitessearchQuery 的最后两个已知值。当这些更改中的任何一个更改时,都会执行该块。我们现在可以订阅 shownCites 并且每次源可观察到的变化都会得到更新的值。