alexxjk alexxjk - 5 months ago 25
Swift Question

RxSwift: Observe rx_text & rx_offset simultaneously

I've been working on a search controller that is using RxSwift to update DataSource when user types in Search field, like it's described here: http://www.thedroidsonroids.com/blog/ios/rxswift-examples-3-networking/

That is my viewmodel:

struct SearchControllerViewModel {

let provider: RxMoyaProvider<ThreadifyEndpoint>
let startsWith: Observable<String>

func startSearching() -> Observable<[SearchedNodeViewModel]> {
return startsWith
.observeOn(MainScheduler.instance)
.flatMapLatest { query -> Observable<[SearchedNodeViewModel]?> in
return self.findNodes(query)
}.replaceNilWith([])


}

internal func findNodes(startsWith: String) -> Observable<[SearchedNodeViewModel]?> {
return self.provider
.request(ThreadifyEndpoint.SearchForNodes(startsWith: startsWith))
.mapArrayOptional(SearchedNodeViewModel.self)
}
}


Now I want new data to be loaded not only when user is typing but either when sh's scrolling down.
I was thinking to use combineLatest to observe both rx_text and rx_offset but I can't pass Observable to combineLatest because of compilation error.

Answer

The compilation error you're seeing is due to you not using an actual method. The method signature you're intending to use is:

public class func combineLatest<O1 : ObservableType, O2 : ObservableType>(source1: O1, _ source2: O2, resultSelector: (O1.E, O2.E) throws -> Element) -> RxSwift.Observable<Element>

Notice that there's a third argument that you're forgetting: resultSelector. That's supposed to be a block that describes how you want to combine the latest elements into a new element.

Based on your error message, I'm thinking you're using it like this:

let combined = Observable.combineLatest(stringObservable, pointObservable)

Whereas, you should be using it like this:

let combined = Observable.combineLatest(stringObservable, pointObservable) { (s, p) in
    return "\(s), \(p)" // or construct your new element however you'd like
}

Without the block, RxSwift doesn't know how you'd like to combine them. You might have been thinking it would just default to making a new tuple of (String, CGPoint) as the element, but it makes no such assumptions and requires you to tell it.