5

您好我正在尝试了解 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>>>')
4

3 回答 3

10

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
}

这里发生了什么 ?

combineLatestallCites取和的最后两个已知值searchQuery。当其中任何一个更改时,都会执行该块。我们现在可以订阅shownCites并在每次源 observable 更改时获取更新的值。

于 2016-03-24T19:00:51.000 回答
2

我让它使用以下代码:

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

但是我仍然想知道原始代码有什么问题。因此,如果有人对我有答案,我将不胜感激。

于 2016-03-24T00:45:09.813 回答
1
    //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)

这段代码应该为你做:)

于 2016-03-24T02:48:42.193 回答