微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 swift collectionView 上遇到分页问题

如何解决在 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()
        }
        
    }
}

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.")
        }
    }
}

问题是我想一次只获取一个 pokemons 数组,但是我同时进行所有端点调用,并将它们附加到我的 generalList 数组中,该数组拥有我的 collectionView 数据源和所有这些东西。

PD: 不知道是否有帮助,但这是我的控制台的屏幕截图。第一个 msg 没问题,但是只有当用户到达 CollectionView 的末尾时它才应该打印其他消息,而且这不会发生(相反,它们都同时返回!)

Screenshot

我不知道如何完成这项工作。我真的很感激任何建议或纠正,谢谢。

解决方法

我知道发生了什么。我正在使用 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。这解决了问题。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。