Swift 如何在反应式扩展中组合两个观察值以对结果进行分页?
我正在尝试使用RxSwift在iOS应用程序中开发分页系统。用例很简单:用户可以在搜索字段中输入文本,应用程序执行分页请求。当他更改值时,在第一页执行一个新的请求(这意味着必须将可观察值重置为1)。如果用户清除搜索字段(或输入少于2个字符的文本),则清除结果列表并重置当前页面。当用户滚动到列表底部时,将获取下一页 这不是swift或iOS特定的情况,我想它可以使用RxKotlin或RxJs或任何其他反应式扩展以相同的方式编写 我目前的尝试是为文本和当前页面设置一个observable,并将它们组合起来,以便使用这两个参数执行请求。 我已经成功地完成了我想要的工作,但是使用了全局属性来存储当前查询和当前页面。我想找到一种方法,只使用可观测物发出的值,而不必维护它们(我想代码会更简洁,更易于阅读和理解) 这是我目前的代码:Swift 如何在反应式扩展中组合两个观察值以对结果进行分页?,swift,reactive-programming,observable,rx-swift,reactivex,Swift,Reactive Programming,Observable,Rx Swift,Reactivex,我正在尝试使用RxSwift在iOS应用程序中开发分页系统。用例很简单:用户可以在搜索字段中输入文本,应用程序执行分页请求。当他更改值时,在第一页执行一个新的请求(这意味着必须将可观察值重置为1)。如果用户清除搜索字段(或输入少于2个字符的文本),则清除结果列表并重置当前页面。当用户滚动到列表底部时,将获取下一页 这不是swift或iOS特定的情况,我想它可以使用RxKotlin或RxJs或任何其他反应式扩展以相同的方式编写 我目前的尝试是为文本和当前页面设置一个observable,并将它们组
// self.nextPage is a Variable<Int>
let moreObs: Observable<Int> = self.nextPage.asObservable()
.distinctUntilChanged() // Emit only if page has changed.
// self.searchTextObservable is a PublishedSubject<String> that receives the values from the textfield
let searchObs: Observable<String> = self.searchTextObservable
.throttle(0.4, scheduler: MainScheduler.instance) // Wait 400ms when the user stops writing.
.distinctUntilChanged() // Emit only if query has changed.
self.resultsObservable = Observable
.combineLatest(searchObs, moreObs) { query, page in
return ["q": query, "p": "\(page)"]
}
.subscribeOn(MainScheduler.instance) // Emit on main thread.
.observeOn(ConcurrentDispatchQueueScheduler(globalConcurrentQueueQOS: .Background)) // Perform on background thread.
.map { params in
if params["q"]!.characters.count > 2 {
return params
}
return [:]
}
.flatMap { params in
return params.isEmpty ?
Observable.of([]) :
self.search(params)
}
.map { results in
if results.count > 0 {
self.results.appendContentsOf(results)
} else {
self.results = []
}
return self.results
}
然后我有两个请求被执行
我是否误用了Rx?我不会使用
CombineTest
。您的页码取决于当前的搜索文本,因此您应该使用flatMapLatest
链接它。这样,您就不必自己负责维护它的状态,而是让操作符链接为您重置它
let disposeBag = DisposeBag()
let searchText = PublishSubject<String>() // search field text
let newPageNeeded = PublishSubject<Void>() // fires when a new page is needed
struct RequestPage {
let query: String
let page: Int
}
let requestNeeded = searchText.asObservable()
.flatMapLatest { text in
newPageNeeded.asObservable()
.startWith(())
.scan(RequestPage(query: text, page: 0)) { request, _ in
return RequestPage(query: text, page: request.page + 1)
}
}
requestNeeded
.subscribeNext { print($0) }
.addDisposableTo(disposeBag)
searchText.onNext("A")
searchText.onNext("B")
newPageNeeded.onNext(())
searchText.onNext("C")
newPageNeeded.onNext(())
newPageNeeded.onNext(())
let dispebag=dispebag()
让searchText=PublishSubject()//搜索字段文本
让NewPageRequired=PublishSubject()//在需要新页面时激发
结构请求页{
让查询:字符串
让页面:Int
}
let requestNeeded=searchText.asObservable()
.flatmap最新版本{text in
newPageNeeded.asObservable()
.startWith(())
.scan(请求页面(查询:文本,页面:0)){request,\ in
返回请求页面(查询:文本,页面:request.page+1)
}
}
请求需要
.subscribebenext{print($0)}
.addDisposableTo(disposeBag)
searchText.onNext(“A”)
searchText.onNext(“B”)
newPageRequired.onNext(())
searchText.onNext(“C”)
newPageRequired.onNext(())
newPageRequired.onNext(())
这将输出:
(请求第1页)(查询:“A”,第1页)(请求第1页)(查询:“B”,第1页)
(请求第1页)(查询:“B”,第2页)
(请求第1页)(查询:“C”,第1页)
(请求第1页)(查询:“C”,第2页)
(第1页)(查询:“C”,第3页)
这太完美了!
let disposeBag = DisposeBag()
let searchText = PublishSubject<String>() // search field text
let newPageNeeded = PublishSubject<Void>() // fires when a new page is needed
struct RequestPage {
let query: String
let page: Int
}
let requestNeeded = searchText.asObservable()
.flatMapLatest { text in
newPageNeeded.asObservable()
.startWith(())
.scan(RequestPage(query: text, page: 0)) { request, _ in
return RequestPage(query: text, page: request.page + 1)
}
}
requestNeeded
.subscribeNext { print($0) }
.addDisposableTo(disposeBag)
searchText.onNext("A")
searchText.onNext("B")
newPageNeeded.onNext(())
searchText.onNext("C")
newPageNeeded.onNext(())
newPageNeeded.onNext(())