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

Swift中TableView底部分页异常:未滚动多次调用接口仅显示10条

问题分析与解决方案

核心问题

  1. 数据被覆盖而非累加:每次请求分页数据后,直接用新的PaymentsHistoryModel替换原有paymentsData,导致之前加载的数据被清空,最终只能显示最后一次请求的页面数据(你看到仅显示前10条,大概率是后续请求的解析或返回出现异常,但逻辑上核心问题是数据未做累加)。
  2. willDisplay被重复触发:每次请求成功后调用tableView.reloadData(),会重新渲染所有cell,包括最后一个cell,这会再次触发willDisplay方法,导致连续发起分页请求,直到currentPage超过totalPages,这就是未滚动就触发4次请求的原因。
  3. 无请求防重机制:没有限制同一时间只能发起一个请求,进一步加剧了重复请求的问题。

修复代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 19:15:36