实现无限滚动分页功能:求页码递增函数(附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
相关产品推荐
相关产品推荐

