2016-03-23 2 views
3

こんにちは私はより良い機能コードを書くためにRxSwiftライブラリの理解を得ようとしています。RxSwift filter可変配列

現在、私は非常に基本的な問題に固執しています。

var allCites: Variable<[CiteModel?]> = Variable([]) 
var shownCites: Variable<[CiteModel?]> = Variable([]) 

今、私はすべてが特定のテキストが含まれているとshownCitesに追加allCites配列から引用しているフィルタリングしたい:私はタイプVariable<[CiteModel?]>のこの変数が持って言うことができます。

これは私のフィルタの内側にブロック$0は私が期待するものを[CiteModel?]ないCiteModel?である私が試してみましたが、それはコンパイルできないものです。私が間違っていたことを私に説明できますか?私はまだ元と間違っていたかを知るしたいしかし

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

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

この情報はどこから届いていますか? Variableクラスのドキュメントが見つかりませんでした。 – dehlen

+0

はい私は、現在取得中のエラーで質問を更新しました。 – dehlen

答えて

6

mapシーケンスの各値に対して操作を実行します。 mapObservable<T>に適用すると、mapは、そのブロックのパラメータとしてTを受け取ります。 Variable<[CiteModel?]>の場合

Observableはしたがって配列T == [CiteModel?]です。

私たちは本当に[CiteModel?]の配列をフィルタリングしたいので、あなたが

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

filterCitesByQueryの定義を変更することができます。しかし、それは行うことが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は、allCitesおよびsearchQueryの最後の2つの既知の値をとります。これらのいずれかが変更されると、ブロックが実行されます。 shownCitesを購読することができ、ソースの観測可能な変更のたびに更新値が取得されます。

+0

すごいなんてすばらしい答え。これははるかに明確になり、私にはそれを行う正しい方法のように見えるので、私はこれを受け入れたものとしてマークします。ありがとう – dehlen

1

私はそれがこのコードで作業しました:上記のコードを実行するときに

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

エラーコード。だから誰かが私のための答えを持っているなら、これは本当に感謝します。

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) 

このコードはあなたのためにそれを行う必要があります:)

+0

RxSwiftのような私の推測よりもはるかに多くのことをありがとう。 – dehlen