2016-03-23 24 views
3

嗨我想了解RxSwift庫來編寫更好的功能代碼。RxSwift filter變量數組

目前我被困在一個非常基本的問題。比方說,我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>>>') 
+0

此信息來自哪裏?我找不到有關變量類的任何文檔。 – dehlen

+0

是的,我更新了我正在得到的錯誤的問題。 – dehlen

回答

6

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取最後2個已知值allCitessearchQuery。當這些變化中的任何一個時,塊被執行。我們現在可以訂閱shownCites,並且每次觀察到任何可觀察到的變化時都會得到更新的值。

+0

哇,多好的答案。這使得它更加清晰,對我來說,它看起來是正確的做法,因此我會將其標記爲已接受。謝謝 – dehlen

1

我得到了它,此代碼的工作:

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

但是我還是想知道這是錯的原碼。所以如果任何人有我的答案,這將非常感激。

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