Swift中处理Web查询后如何延迟调用endRefreshing并解决相关异常
问题原因
- 短时间内多次触发下拉刷新会导致
didUpdateAlerts被多次调用,你现有的实现没有取消之前提交的延迟任务,多个任务先后执行就会出现打印多次、延迟时长不符合预期的问题 UITableView.reloadData()是异步操作,调用后不会立刻完成列表渲染,你现有代码的计时起点是reloadData()的调用时间,不是列表真正完成刷新的时间
修复方案
你可以用可取消的DispatchWorkItem管理延迟任务,同时可以搭配CATransaction捕获列表刷新完成的时机,实现精准延迟:
- 首先在控制器类中声明一个变量存储延迟任务:
private var endRefreshWorkItem: DispatchWorkItem?
- 修改
didUpdateAlerts的实现:
func didUpdateAlerts(alerts: [String:String]){ DispatchQueue.main.async { // 取消之前未执行的结束刷新任务,避免多次调用冲突 self.endRefreshWorkItem?.cancel() self.serviceDictionary = alerts self.tableView.reloadData() // 构建新的结束刷新任务 let workItem = DispatchWorkItem { [weak self] in guard let self = self, self.refreshAlertsControl.isRefreshing else { return } self.refreshAlertsControl.endRefreshing() print("After 1 sec delay - alertRefresh") } self.endRefreshWorkItem = workItem // 等待列表渲染完成后再开始计时 CATransaction.begin() CATransaction.setCompletionBlock { // 延迟1秒执行结束刷新逻辑 DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: workItem) } CATransaction.commit() } }
- 可选:在控制器销毁时取消未执行的任务,避免不必要的资源占用:
deinit { endRefreshWorkItem?.cancel() }
如果你不需要严格对齐列表渲染完成的时机,也可以直接去掉CATransaction相关代码,直接提交延迟任务即可。
内容的提问来源于stack exchange,提问作者Shonie
相关产品推荐
相关产品推荐

