Swift中TableView底部分页异常:未滚动多次调用接口仅显示10条
问题分析与解决方案
核心问题
- 数据被覆盖而非累加:每次请求分页数据后,直接用新的
PaymentsHistoryModel替换原有paymentsData,导致之前加载的数据被清空,最终只能显示最后一次请求的页面数据(你看到仅显示前10条,大概率是后续请求的解析或返回出现异常,但逻辑上核心问题是数据未做累加)。 willDisplay被重复触发:每次请求成功后调用tableView.reloadData(),会重新渲染所有cell,包括最后一个cell,这会再次触发willDisplay方法,导致连续发起分页请求,直到currentPage超过totalPages,这就是未滚动就触发4次请求的原因。- 无请求防重机制:没有限制同一时间只能发起一个请求,进一步加剧了重复请求的问题。
修复代码
1. 修改数据存储结构
将单独的paymentsData拆分为存储元数据的变量,以及用于累加所有支付记录的数组:
class MyPaymentsViewController: UIViewController { @IBOutlet weak var tableView: UITableView! private var currentPage = 1 private var totalPages = 1 // 存储所有支付记录的数组,用于累加分页数据 private var paymentsList: [PaymentModel] = [] // 替换成你实际的支付数据模型类型 private var isLoading = false // 防止重复请求的锁 override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 进入页面时重置所有状态 currentPage = 1 totalPages = 1 paymentsList.removeAll() isLoading = false paymentsServiceCall() } func paymentsServiceCall() { guard !isLoading else { return } // 正在加载时不发起新请求 isLoading = true let param = ["page_no": currentPage] serviceCall(param: param, method: .post, url: CommonUrl.student_my_payments) { [weak self] (resp) in guard let self = self else { return } defer { self.isLoading = false } // 请求完成后解锁 if let resultDict = resp.dict?["result"] as? NSDictionary { let newPageData = PaymentsHistoryModel(dictionary: resp.dict as NSDictionary? ?? NSDictionary()) // 更新总页数 self.totalPages = newPageData.result?.page_count ?? 0 // 将新页面的支付记录追加到数组 if let newPayments = newPageData.result?.payments { self.paymentsList.append(contentsOf: newPayments) } // 刷新表格 self.tableView.reloadData() } } } }
2. 修正UITableView代理方法
extension MyPaymentsViewController: UITableViewDelegate, UITableViewDataSource { func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { // 仅当当前是最后一个cell、不在加载中、还有更多页时,才发起下一页请求 if indexPath.row == paymentsList.count - 1, !isLoading, currentPage < totalPages { print("加载下一页") currentPage += 1 paymentsServiceCall() } } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { paymentsList.count } // 记得实现cellForRowAt方法,用paymentsList的数据渲染cell func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "你的CellID", for: indexPath) let payment = paymentsList[indexPath.row] // 配置cell内容(根据你的模型字段设置UI) return cell } }
额外注意事项
- 确保
PaymentsHistoryModel中payments数组的类型是可遍历集合,能通过append(contentsOf:)正常追加数据。 - 核对JSON字段与模型的映射关系,比如JSON中的
Payments是大写开头,要保证模型解析时字段匹配,避免新页面数据为空。 - 可在tableView底部添加加载提示的footerView,提升用户体验。
内容的提问来源于stack exchange,提问作者SwiftABC
相关产品推荐
相关产品推荐

