gpt4 book ai didi

swift - 使用 RxSwift 刷新下一页

转载 作者:行者123 更新时间:2023-11-28 15:07:49 24 4
gpt4 key购买 nike

我正在使用 RxSwift 拉取刷新和刷新下一页。

目前,这是我目前使用的 viewModel:

public final class MomentViewModel {
// Property
let refreshTrigger = PublishSubject<Void>()
let loadNextPageTrigger = PublishSubject<Void>()
let loading = Variable<Bool>(false)
let posts = Variable<[Post]>([])
var pageIndex: Int = 0
let error = PublishSubject<Swift.Error>()
private let disposeBag = DisposeBag()

public init() {

let refreshRequest = loading.asObservable()
.sample(refreshTrigger)
.flatMap { loading -> Observable<Int> in
if loading {
return Observable.empty()
} else {
return Observable<Int>.create { observer in
self.pageIndex = 0
print("reset page index to 0")
observer.onNext(0)
observer.onCompleted()
return Disposables.create()
}
}
}
.debug("refreshRequest", trimOutput: false)

let nextPageRequest = loading.asObservable()
.sample(loadNextPageTrigger)
.flatMap { loading -> Observable<Int> in
if loading {
return Observable.empty()
} else {
return Observable<Int>.create { [unowned self] observer in
self.pageIndex += 1
print(self.pageIndex)
observer.onNext(self.pageIndex)
observer.onCompleted()
return Disposables.create()
}
}
}
.debug("nextPageRequest", trimOutput: false)

let request = Observable.merge(refreshRequest, nextPageRequest)
.debug("Request", trimOutput: false)

let response = request.flatMapLatest { page in
RxAPIProvider.shared.getPostList(page: page).materialize()
}
.share(replay: 1)
.elements()
.debug("Response", trimOutput: false)

Observable
.combineLatest(request, response, posts.asObservable()) { request, response, posts in
return self.pageIndex == 0 ? response : posts + response
}
.sample(response)
.bind(to: posts)
.disposed(by: disposeBag)

Observable
.merge(request.map{ _ in true },
response.map { _ in false },
error.map { _ in false })
.bind(to: loading)
.disposed(by: disposeBag)
}
}

refreshTriggerloadNextPageTrigger 绑定(bind)到不同的目标 likes:

self.tableView.rx_reachedBottom
.map { _ in () }
.bind(to: self.viewModel.loadNextPageTrigger)
.disposed(by: disposeBag)

self.refreshControl.rx.controlEvent(.valueChanged)
.bind(to: self.viewModel.refreshTrigger)
.disposed(by: disposeBag)


self.rx.sentMessage(#selector(UIViewController.viewWillAppear(_:)))
.map { _ in () }
.bind(to: viewModel.refreshTrigger)
.disposed(by: disposeBag)

问题:

当我将 tableView 滚动到底部并触发 loadNextPageTrigger 时,一切正常。

但是,如果下一个请求没有更多的数据,loadnextPageTrigger将被无限触发。任何帮助将不胜感激。

您可以下载 Demo这里。

最佳答案

主要思想是检查是否加载了所有元素。我在源代码中发现你加载了 20 个部件,所以这个条件应该可以正常工作 if loadedPosts < 20 then stop loading new part .在这里,我与您分享您可以根据需要重构的基本解决方案(因为我不擅长 RxSwift ):

MomentViewModel你应该申报属性(property)

private var isAllLoaded = false

如果加载所有值,则设置为 true。然后你应该检查每个 [Post]响应设置正确 isAllLoaded :

Observable
.combineLatest(request, response, posts.asObservable()) { request, response, posts in
self.isAllLoaded = response.count < 20 // here the check
return self.pageIndex == 0 ? response : posts + response
}
.sample(response)
.bind(to: posts)
.disposed(by: disposeBag)

然后在nextPageRequest在你应该返回.empty()观察者是否已加载所有部分:

if loading {
return Observable.empty()
} else {
guard !self.isAllLoaded else { return Observable.empty() }

return Observable<Int>.create { [unowned self] observer in
self.pageIndex += 1
print(self.pageIndex)
observer.onNext(self.pageIndex)
observer.onCompleted()
return Disposables.create()
}
}

附言 MomentViewModel.swift 要复制/粘贴的文件。

关于swift - 使用 RxSwift 刷新下一页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48225276/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com