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

TableView reloadData正确时机:基于DispatchGroup优化数据加载

使用DispatchGroup实现批量数据拉取后仅刷新一次TableView

嘿,这个需求用DispatchGroup绝对是最优解!它能帮你精准追踪所有异步数据请求的完成状态,等所有请求都结束后再统一刷新TableView,彻底解决之前频繁刷新带来的性能损耗和视觉卡顿问题。下面是具体的实现步骤和代码示例:

1. 初始化核心变量

首先在你的ViewController里定义好存储数据的数组,以及一个DispatchGroup实例:

var events: [Event] = [] // 这里假设Event是你的数据模型类/结构体
let dataFetchGroup = DispatchGroup() // 给group起个有意义的名字,可读性更好

2. 改造数据拉取逻辑

不管你是单次拉取多组数据,还是分页拉取多次,都要把每个异步请求纳入DispatchGroup的管理:

// 示例:如果是分页拉取,循环发起请求
let totalPages = 3 // 假设你要拉取3页数据
for pageIndex in 1...totalPages {
    dataFetchGroup.enter() // 标记一个新的异步任务开始
    
    self.fetchEventsFromServer(page: pageIndex) { [weak self] result in
        defer {
            self?.dataFetchGroup.leave() // 无论请求成功/失败,都标记任务结束
        }
        
        guard let self = self else { return }
        
        switch result {
        case .success(let newEvents):
            self.events.append(contentsOf: newEvents) // 批量追加数据,暂不刷新
        case .failure(let error):
            print("拉取第\(pageIndex)页失败:\(error.localizedDescription)")
            // 这里可以根据需求处理错误,比如记录日志或提示用户
        }
    }
}

如果你的fetchEventsFromServer内部包含多个并行的子请求,同样的逻辑:每个子请求前调用enter(),完成后调用leave()即可。

3. 监听所有任务完成,统一刷新UI

通过DispatchGroup的notify方法,我们可以在所有任务都完成后触发统一的刷新操作,注意一定要回到主队列执行UI操作:

dataFetchGroup.notify(queue: DispatchQueue.main) { [weak self] in
    guard let self = self else { return }
    // 所有数据拉取&追加完成,仅刷新一次TableView
    self.tableView.reloadData()
    // 还可以在这里做其他收尾工作,比如隐藏加载指示器、更新空状态等
}

必看的关键细节

  • enter()和leave()必须严格配对:每调用一次enter(),就必须对应一次leave(),哪怕请求失败、抛出异常也要执行,否则DispatchGroup会一直处于等待状态,notify永远不会触发。用defer块是最稳妥的方式,确保无论代码走哪个分支都会执行leave()。
  • UI操作务必在主队列:TableView的刷新属于UI操作,必须放在主队列执行,否则会导致UI错乱甚至崩溃。
  • 避免循环引用:闭包里使用[weak self]捕获,防止ViewController因为被闭包强引用而无法释放。

这样改造后,你就再也不会出现每次追加数据就刷新TableView的问题了,所有数据准备好后才会触发一次刷新,既提升了性能,也优化了用户体验!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 07:58:24