You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现无限滚动分页功能:求页码递增函数(附API调用代码)

实现无限滚动分页的解决方案

修改后的完整代码

class CoinDataService: ObservableObject {

    @Published var allCoins: [CoinModel] = []
    @Published var isLoading: Bool = false

    var coinSubscription: AnyCancellable?

    var coinListFull = false
    var currentPage = 1 // CoinGecko API页码从1开始,修正初始值
    let perPage = 200
    var canLoadMorePages = true

    init() {
        getCoins()
    }

    public func getCoins() {
        guard !isLoading && canLoadMorePages else { return }
        
        isLoading = true
        guard let url = URL(string: "https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=\(perPage)&page=\(currentPage)&sparkline=true&price_change_percentage=24h") else {
            isLoading = false
            return
        }

        coinSubscription = NetworkingManager.download(url: url)
            .decode(type: [CoinModel].self, decoder: JSONDecoder())
            .receive(on: DispatchQueue.main)
            .sink(
                receiveCompletion: { [weak self] completion in
                    NetworkingManager.handleCompletion(completion)
                    self?.isLoading = false // 请求完成后再关闭加载状态
                    if case .failure = completion {
                        self?.canLoadMorePages = false // 请求失败时暂时禁止加载更多
                    }
                },
                receiveValue: { [weak self] returnedCoins in
                    guard let self = self else { return }
                    // 追加新数据,而非替换原有数据
                    self.allCoins.append(contentsOf: returnedCoins)
                    self.currentPage += 1 // 成功获取数据后递增页码
                    
                    // 返回数据不足一页时,标记为已加载全部数据
                    if returnedCoins.count < self.perPage {
                        self.coinListFull = true
                        self.canLoadMorePages = false
                    }
                }
            )
    }

    // 供UI层触发的下一页加载函数
    public func loadNextPage() {
        guard !coinListFull else { return }
        getCoins()
    }
}

关键改动说明

  • 页码初始值修正:将原currentpage改为currentPage并设为1,适配CoinGecko API的页码规则(从1开始),避免请求无效数据。
  • 数据累加逻辑:把self?.allCoins = returnedCoins替换为self.allCoins.append(contentsOf: returnedCoins),保留已加载数据,实现滚动累加效果。
  • 加载状态管理:将isLoading = false移到请求完成的回调中,避免请求还在进行时就标记为未加载,防止重复触发请求。
  • 页码自动递增:在成功获取数据后执行currentPage += 1,确保下一次请求指向正确的下一页。
  • 终止加载判断:当返回数据量小于每页设定值时,关闭canLoadMorePages并标记coinListFull,避免无效的后续请求。
  • 新增触发函数:添加loadNextPage(),可以直接在UI层(如列表底部的加载提示出现时)调用,触发下一页数据加载。

SwiftUI UI层调用示例

List {
    ForEach(coinDataService.allCoins) { coin in
        CoinRowView(coin: coin)
    }
    // 列表底部显示加载提示,出现时触发下一页加载
    if coinDataService.isLoading {
        ProgressView()
            .onAppear {
                coinDataService.loadNextPage()
            }
    }
}

内容的提问来源于stack exchange,提问作者Wilson Agene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 10:19:52