SwiftUI实现分页功能时无法加载第2页及后续页面问题求助
SwiftUI 分页无法加载第2页及后续页面的问题修复
问题原因
- 缺少加载中状态拦截:触发下一页加载的逻辑没有判断当前是否已有正在执行的请求,滚动到列表底部时会多次触发加载逻辑,导致page参数被异常累加,跳过第2页直接请求更高页码,同时也会引发请求错乱。
- isLastItem方法存在类型安全隐患:扩展中额外定义的泛型Item和集合自身的Element类型没有绑定,使用AnyHashable对比id可能出现误判,导致第二页加载完成后无法正确识别新的列表最后一项,无法触发后续加载。
- 加载状态未正确重置:如果loadData请求完成后没有将isLoading重置为false,后续所有的下一页加载逻辑都会被拦截。
- 潜在的分页参数不匹配:GitHub OpenAPI的page参数从1开始计数,若初始page值设置错误,会出现重复请求同一页的问题,导致列表长度不符合预期,无法触发下一页加载。
修复方案
1. 修正最后一项判断扩展
移除冗余泛型,保证类型匹配,避免id对比误判:
extension RandomAccessCollection where Element: Identifiable { public func isLastItem(_ item: Element) -> Bool { guard !isEmpty else { return false } guard let itemIndex = firstIndex(where: { $0.id == item.id }) else { return false } let distance = self.distance(from: itemIndex, to: endIndex) // 可调整为distance <= 2 提前触发加载,优化用户体验 return distance == 1 } }
2. 优化下一页触发逻辑
新增加载中状态判断,避免重复触发请求:
private extension ContentView { // 此处的Repository替换为你实际的列表数据模型类型 func listItemAppears(_ item: Repository) { guard !isLoading, items.isLastItem(item) else { return } isLoading = true page += 1 loadData() } }
3. 完善数据请求逻辑
请求完成后统一重置加载状态,请求失败时回退page参数,新数据追加到原有列表后:
func loadData() { guard let url = URL(string: "https://api.github.com/search/repositories?q=swift&sort=stars&per_page=20&page=\(page)") else { isLoading = false return } URLSession.shared.dataTask(with: url) { [weak self] data, response, error in // 无论请求成功失败,最终都要重置加载状态 defer { DispatchQueue.main.async { self?.isLoading = false } } if let error = error { // 请求失败时回退page,避免后续请求跳过当前页 DispatchQueue.main.async { self?.page -= 1 } print(error.localizedDescription) return } guard let data = data, let result = try? JSONDecoder().decode(SearchResponse.self, from: data) else { return } DispatchQueue.main.async { // 新数据追加到原有数组,不要直接覆盖 self?.items.append(contentsOf: result.items) // 可选优化:返回数据量小于每页数量时标记没有更多数据,后续不再触发加载 if result.items.count < 20 { self?.hasMoreData = false } } }.resume() }
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

