RxSwift过滤器变量数组

时间:2016-03-23 23:56:46

标签: ios swift functional-programming rx-swift

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

目前我遇到了一个非常基本的问题。假设我得到了rev = reverse(s.substring(0,index));类型的变量:

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)
    }
}

3 个答案:

答案 0 :(得分:9)

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
}

这里发生了什么?

combineLatest获取allCitessearchQuery的最后2个已知值。当其中任何一个发生更改时,都会执行该块。我们现在可以订阅shownCites,并且每次在源可观察的更改中都会获得更新的值。

答案 1 :(得分:1)

我使用了这段代码:

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

但是我仍然想知道原始代码出了什么问题。所以,如果有人对我有答案,那将非常感激。

答案 2 :(得分: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)

此代码应该为您完成:)