pop返回ViewController时如何正确刷新UITableView数据
问题根因
reloadData方法执行后列表未更新,核心原因是调用刷新方法时,UITableView对应的数据源diaryList没有更新为上传后的最新数据,仅触发刷新逻辑、不更新数据源,自然无法渲染出最新内容。另外如果刷新操作不在主线程执行,也会出现UI不更新的异常。
可落地解决方案
- 修正生命周期方法内的刷新逻辑
不要在viewWillAppear/viewDidAppear中仅单独调用tableView.reloadData(),需要先拉取最新数据,等数据源完成赋值后,再在主线程触发刷新。参考写法:
注意:所有UI相关操作必须放在主线程执行,子线程调用override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) // 1. 从接口/本地存储拉取更新后的日记列表数据 fetchUpdatedDiaryData { [weak self] latestData in guard let self = self else { return } // 2. 给数据源数组赋值最新内容 self.diaryList = latestData // 3. 主线程执行UI刷新 DispatchQueue.main.async { self.tableView.reloadData() } } }reloadData会出现刷新不及时、不生效的问题。 - 用反向传值实现精准刷新(性能更优)
如果不想每次页面展示都重新拉取全量数据,可以在数据上传页和列表页之间做反向传值,上传成功后直接把最新数据传回列表页,更新对应数据源后刷新即可,常用的实现方式有闭包、代理、通知三种,以闭包为例:- 在数据上传页定义传值用的闭包属性:
// 上传成功后回传最新日记条目的闭包 var onUploadSuccess: ((_ updatedDiaryItem: DiaryListJsonValue.DiaryListNew.Monthly) -> Void)?- 上传接口请求成功、执行pop操作前,调用闭包传回最新数据:
// 上传成功逻辑处理完成后 self.onUploadSuccess?(newDiaryItem) self.navigationController?.popViewController(animated: true)- 列表页跳转时绑定闭包回调,收到新数据后更新数据源、刷新列表:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard let uploadVC = segue.destination as? DataUploadViewController else { return } uploadVC.onUploadSuccess = { [weak self] updatedItem in guard let self = self else { return } // 根据业务逻辑更新diaryList中对应位置的旧数据 // 主线程刷新列表 DispatchQueue.main.async { self.tableView.reloadData() } } } - 现有代码问题修正
你贴出的cellForRowAt代理方法中,判断expandedcells是否包含当前indexPath的if分支缺少闭合大括号,正式代码需要补全避免逻辑异常;另外更新diaryList数据源时,建议同步重置expandedcells数组,避免indexPath不匹配导致的数组越界问题。
内容的提问来源于stack exchange,提问作者JJHA
相关产品推荐
相关产品推荐

