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

Swift中UITableViewDataSource加载更多时isEnd未更新且无法刷新的问题

问题分析与解决方案

看起来你遇到的核心问题有两个:一是每次加载更多时都会重新创建JBCJobsDataSource实例,导致旧实例的isEnd永远得不到更新;二是willDisplay里用了重复触发的Timer,即使没有更多数据也会持续调用接口,同时数据追加逻辑错误导致table无法正常刷新。下面是具体的修复步骤:

1. 避免重复创建数据源实例

在你的ViewController中,每次调用loadMoreJobs时都执行了self.jobsDataSource = JBCJobsDataSource(),这会丢弃之前的数据源对象,新的isEnd值只会存在于新实例中,而tableView绑定的还是旧实例(或者被重新绑定但逻辑混乱)。

修改ViewController的初始化逻辑:
在viewDidLoad中只初始化一次数据源,而不是每次加载更多都新建:

override func viewDidLoad() {
    super.viewDidLoad()
    // 初始化一次数据源
    self.jobsDataSource = JBCJobsDataSource()
    self.jobsDataSource?.jobTableView = self.jobTableView
    // 加载第一页数据
    loadMoreJobs(page: 1)
}

修改loadMoreJobs的成功回调:
不再重建数据源,而是追加新数据并更新isEnd:

func loadMoreJobs(page: Int) {
    let params = [
        "session_token": JBCSettings.sessionToken,
        "page_count": "\(page)"
    ]
    JBCService.shared.getService(request: JBCRouter.jobs(params), callbackSuccess: { (obj: ObjectJobs?) in
        guard let obj = obj, obj.status == 1 else { return }
        
        // 追加新数据到现有数据源,而不是替换整个数组
        if let newJobs = obj.jobList {
            self.jobsDataSource?.job.append(contentsOf: newJobs)
        }
        // 更新isEnd状态
        self.jobsDataSource?.isEnd = obj.end ?? 0
        // 请求完成后重置加载状态
        self.jobsDataSource?.isLoading = false
        
    }) { (status, obj) in
        // 错误回调中也要重置加载状态
        self.jobsDataSource?.isLoading = false
    }
}

2. 修复JBCJobsDataSource中的加载逻辑

原来的willDisplay用了重复Timer,会导致多次触发接口请求,而且没有判断是否还有更多数据(应该是isEnd == 0时才加载),同时需要添加一个加载锁防止重复请求。

修改JBCJobsDataSource:

class JBCJobsDataSource: NSObject {

    var job = [JobObject]() {
        didSet {
            reloadTableView()
        }
    }
    var isEnd: Int = 0
    // 添加加载锁,防止重复请求
    var isLoading: Bool = false

    weak var jobTableView: UITableView? {
        didSet {
            setupTableView()
        }
    }

    func setupTableView() {
        if jobTableView != nil {
            jobTableView?.backgroundColor = UIColor.clear
            jobTableView!.delegate =  self
            jobTableView!.dataSource = self
            jobTableView!.register(UINib(nibName: "JobCell", bundle: nil), forCellReuseIdentifier: JobCell.cellIdentify())
        }
    }

    func reloadTableView() {
        DispatchQueue.main.async {
            self.jobTableView?.reloadData()
        }
    }
}

extension JBCJobsDataSource: UITableViewDelegate, UITableViewDataSource {

    func dataForRowAtIndexPath(_ indexPath:IndexPath) -> JobObject {
        return job[indexPath.row]
    }

    // ... 其他原有代理方法不变 ...

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        // 只有当滚动到最后一行、还有更多数据、且当前没有在加载时,才触发加载更多
        let isLastRow = (indexPath.row + 1) == job.count
        let hasMoreData = isEnd == 0
        if isLastRow && hasMoreData && !isLoading {
            isLoading = true // 标记为加载中
            JBCServiceExecute.jobNoti(page: true)
        }
    }
}

3. 移除重复触发的Timer

原来的Timer会持续发送加载通知,即使没有更多数据也不会停止,直接去掉Timer后,配合isLoading锁就能避免重复请求,同时保证只有在符合条件时才触发加载。

4. 确保tableView刷新正常

因为job数组的didSet会自动调用reloadTableView(),现在我们是追加数据而不是替换整个数组,所以tableView会自动刷新新数据。如果需要更平滑的加载动画,也可以改用insertRows方法插入新行,但当前逻辑下直接追加已经能正常刷新。

这样修改后,isEnd会被正确更新,加载更多的逻辑只会在有数据且未加载时触发,tableView也能正常显示新数据了。

内容的提问来源于stack exchange,提问作者Pyae Phyoe Shein

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:19:24