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

iOS UITableView无限滚动加载更多单元格失败求助

解决UITableView无限滚动无法插入单元格的问题

我帮你排查了代码里的几个关键问题,这就是你无法加载更多单元格的原因,以及对应的修复方案:

核心问题分析

1. 滚动触底判断与请求参数错误

你在willDisplay里的触底判断逻辑本身能触发,但后续加载更多时,硬写了offset:10而非使用currentOffset变量,这会导致每次都拉取重复数据,而且插入行的逻辑也不对。

2. 插入多行的IndexPath生成错误

你现在只生成了单个IndexPath来插入,但明明append了10条数据,表格需要知道要插入10行对应的位置,不然只会显示一行新数据,剩下的都不会被渲染。

3. 缺少重复请求拦截

没有添加加载状态标记,用户快速滚动时可能会多次触发加载请求,导致数据重复或性能问题。

修复后的完整代码

我标注了所有修改的地方,你可以直接替换测试:

import UIKit
class FeedViewController: UIViewController {
    @IBOutlet weak var feedTableView: UITableView!
    let popularPlaces = getPopularPlaces()
    var firstLoad = true
    var currentOffset = 0
    var venueData = venueDataRequest(query:"Any",offset:0,amount:10)
    // 添加加载状态标记,防止重复请求
    var isLoading = false

    override func viewDidLoad() {
        super.viewDidLoad()
        feedTableView.dataSource = self
        feedTableView.delegate = self
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

extension FeedViewController: UITableViewDelegate{
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        // 修正:直接通过表格获取最后一行索引,更可靠
        let lastRowIndex = tableView.numberOfRows(inSection: 0) - 1
        if indexPath.row == lastRowIndex && !isLoading {
            print(venueData.count)
            print("触发加载更多")
            
            if firstLoad {
                firstLoad = false
                return
            }
            
            isLoading = true
            let appendAmount = 10
            currentOffset += appendAmount
            
            // 修正:使用currentOffset作为请求偏移量
            let res = venueDataRequest(query:"Any",offset: currentOffset,amount:appendAmount)
            let oldCount = venueData.count
            venueData.append(contentsOf: res )
            
            // 修正:生成10行对应的IndexPath数组
            var indexPathsToInsert: [IndexPath] = []
            for row in oldCount + 1 ... oldCount + appendAmount {
                indexPathsToInsert.append(IndexPath(row: row, section: 0))
            }
            
            // 确保在主线程更新UI(如果你的请求是异步的,这里要注意)
            DispatchQueue.main.async {
                self.feedTableView.beginUpdates()
                self.feedTableView.insertRows(at: indexPathsToInsert, with: .automatic)
                self.feedTableView.endUpdates()
                self.isLoading = false
            }
        }
    }
}

extension FeedViewController: UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1 + venueData.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "FeedPopularPlaceCollectionViewTableViewCell", for: indexPath) as! FeedPopularPlaceCollectionViewTableViewCell
            cell.setup()
            return cell
        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: "FeedVenueTableViewCell", for: indexPath) as! FeedVenueTableViewCell
            let pos = indexPath.row - 1
            cell.venueName.text = venueData[pos].name
            cell.venueImage.image = venueData[pos].image
            return cell
        }
    }
}

关于单元格类型识别的说明

你当前的cellForRowAt逻辑是完全正确的:第0行固定返回CollectionView单元格,其他行返回常规图片单元格。只要插入的IndexPath是正确的,UITableView会自动调用这个方法获取对应类型的单元格,所以这部分不需要修改。

额外优化建议

  • 如果你的venueDataRequest是同步网络请求,一定要放到后台线程执行,避免阻塞主线程导致界面卡顿
  • 可以在加载时添加一个底部加载指示器,提升用户体验
  • 建议对拉取的数据做判空处理,避免空数据时执行无效的插入操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:25:45