在 swift collectionView 上遇到分页问题
Posted
技术标签:
【中文标题】在 swift collectionView 上遇到分页问题【英文标题】:Having troubles with pagination on swift collectionView 【发布时间】:2020-12-23 21:28:14 【问题描述】:我的目标是在用户到达我的 collectionViewPokemon 末尾时加载更多信息,但我用来实现此目的的 getPokes
函数被调用 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()
scrollViewDidScroll 方法(这里是错误)
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.")
问题是我想一次只获取一个口袋妖怪数组,但我同时进行所有端点调用,并将它们附加到我的 generalList 数组中,该数组拥有我的 collectionView 数据源和所有这些东西。
PD:如果有帮助,我想知道,但这是我的控制台的屏幕截图。第一个消息没问题,但只有当用户到达 CollectionView 的末尾时它才应该打印其他消息,而且,这不会发生(相反,它们都会同时返回!)
我不知道如何完成这项工作。非常感谢任何建议或更正,谢谢。
【问题讨论】:
一个叫topCalls的人从哪里来的? 每次调用我会得到 20 个宠物小精灵(这是限制属性),所以我只使用 100 个宠物小精灵(并且只打 5 个电话)。 topCalls 只存储该计算,因此 while 语句一直运行直到达到所需的 pokemon 数量 【参考方案1】:我知道发生了什么。我正在使用 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
【讨论】:
以上是关于在 swift collectionView 上遇到分页问题的主要内容,如果未能解决你的问题,请参考以下文章
在 Swift 3 中使用 CGSize 的 collectionView 的 100% 宽度
Swift -collectionView 单元格内的属性在 collectionView.performBatchUpdates > reloadItems(at:) 运行后没有更新
在 Swift 中以编程方式为 CollectionView 设置插图