【问题标题】:Having troubles with pagination on swift collectionView在 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 数量

标签: swift pagination uicollectionview


【解决方案1】:

我知道发生了什么。我正在使用 while 语句重复我的 Api 调用,只要它满足它的条件(limit

所以,我想出了一些不使用该 while 语句的方法,并最终使用一个函数来构造每个 URL,然后设置一个 shouldPage 参数来检查是否需要执行该 apiCall。

我的代码是这样结束的:

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
}

那是在我的服务课上。因此,在我的 CollectionView 数据源中,我在 cellForItemAt 上调用 getPokes(shouldPage: false),在 willDisplay 单元中我说 shouldPage 为 true。这解决了问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-08
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    • 2021-08-28
    • 2015-09-07
    • 2022-11-24
    • 2017-09-18
    相关资源
    最近更新 更多