如何解决在 swift collectionView 上遇到分页问题
我的目标是在用户到达我的 collectionViewPokemon 末尾时加载更多信息,但是我用来实现此目的的 getPokes
func 被调用 X 次,对应于我实现的 while 语句从其他端点获取信息。这与我预期的行为相去甚远。
这是我的代码的样子:
服务类
class Service {
let baseUrl = "https://pokeapi.co/api/v2/pokemon"
let limit = 20
var offset = 0
var isPaginating = false
func getPokes(pagination: Bool = false,handler: @escaping ([Pokemon]) -> Void) {
let topCalls = (limit*5)-limit
let originalPokes = [Pokemon]()
let morePokemons = [Pokemon]()
var endpoint = "\(baseUrl)/?limit=\(limit)&offset=\(offset)"
if pagination {
while offset < topCalls {
isPaginating = true
offset += limit
endpoint = "\(baseUrl)/?limit=\(limit)&offset=\(offset)"
self.mainApiCall(mainList: morePokemons,endpoint: endpoint) { (result) in
switch result {
case .success(let pokemons):
handler(pokemons)
if pagination {
self.isPaginating = true
}
case .failure(let error):
print(error)
}
}
}
} else {
self.mainApiCall(mainList: originalPokes,endpoint: endpoint) { (result) in
switch result {
case .success(let pokemons):
handler(pokemons)
case .failure(let error):
print(error)
}
}
}
}
ViewController 类(属性)
class ViewController: UIViewController,UICollectionViewDelegateFlowLayout,UICollectionViewDelegate,UICollectionViewDataSource,uiscrollviewdelegate {
private let service = Service()
private var pagingChecker = false
var generalList = [Pokemon]()
var pokemons = [Pokemon]()
var morePokemons = [Pokemon]()
. . .
}
viewDidLoad 方法(目前没问题)
override func viewDidLoad() {
super.viewDidLoad()
setViews()
service.getPokes(pagination: false) { [self] (pokes) in
pokemons = pokes
generalList += pokemons
dispatchQueue.main.async {
collectionViewPokemon?.reloadData()
}
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let position = scrollView.contentOffset.y
if position > ((collectionViewPokemon!.contentSize.height) - 200 - scrollView.frame.size.height) {
guard !service.isPaginating else { return }
if !pagingChecker {
service.getPokes(pagination: true) { [self] (morePokes) in
morePokemons = morePokes
generalList += morePokemons
dispatchQueue.main.async {
collectionViewPokemon?.reloadData()
}
}
} else {
pagingChecker = true
print("Done paging.")
}
}
}
问题是我想一次只获取一个 pokemons 数组,但是我同时进行所有端点调用,并将它们附加到我的 generalList 数组中,该数组拥有我的 collectionView 数据源和所有这些东西。
PD: 不知道是否有帮助,但这是我的控制台的屏幕截图。第一个 msg 没问题,但是只有当用户到达 CollectionView 的末尾时它才应该打印其他消息,而且这不会发生(相反,它们都同时返回!)
我不知道如何完成这项工作。我真的很感激任何建议或纠正,谢谢。
解决方法
我知道发生了什么。我正在使用 while 语句重复我的 Api 调用,只要它满足它的条件 (limit 所以,我想出了一些不使用 while 语句的方法,最终使用一个函数来构造每个 URL,然后设置一个 shouldPage 参数来检查是否需要完成该 apiCall。 我的代码是这样结束的: 那是我的服务类。因此,在我的 CollectionView 数据源中,我在 cellForItemAt 上调用 getPokes(shouldPage: false),在 willDisplay 单元格中我说 shouldPage 为 true。这解决了问题。let baseUrl = "https://pokeapi.co/api/v2/pokemon"
let limit = 20
var offset = 0
func getPokes(pageNumber: Int = 1,shouldPage: Bool = true,handler: @escaping ([Pokemon]) -> Void) {
let originalPokes = [Pokemon]()
let morePokemons = [Pokemon]()
let endpoint = buildEndpoint(shouldPage: shouldPage)
if shouldPage {
mainApiCall(mainList: morePokemons,endpoint: endpoint) { (result) in
switch result {
case .success(let pokemons):
handler(pokemons)
case .failure(let error):
print(error)
}
}
} else {
mainApiCall(mainList: originalPokes,endpoint: endpoint) { (result) in
switch result {
case .success(let pokemons):
handler(pokemons)
case .failure(let error):
print(error)
}
}
}
}
private func buildEndpoint(shouldPage: Bool = false) -> String {
var endpoint = "\(baseUrl)/?limit=\(limit)&offset=\(offset)"
if shouldPage {
offset += limit
endpoint = "\(baseUrl)/?limit=\(limit)&offset=\(offset)"
}
return endpoint
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。