iOS UITableView 图片刷新闪烁问题记录

一. 问题背景

项目中遇到一个问题,就是当App不在首页的时候,切换到其他App比如微信,然后返回App当前页面,然后从当前页面返回首页,会在首页viewWillAppear这里去拉取是否有未完成订单的接口,刷新UITableView,这时会出现广告位闪烁问题。

二. 问题排查

1.原因分析

这个问题经过断点调试和排除法,发现只要当App进入后台后,回来刷新首页的UITableView都有可能出现闪烁现象。

因此首先我们对图片的加载做延迟操作,并在Cell生成方法调用里面添加相关打印:

可以看到如下打印日志:

从打印日志我们可以看出来,调用reloadData方法后,原来UITableViewcell位置会调整。

但是如果我们App没有进入后台,而是直接调用UITableViewreloadData方法,并不会出现闪烁现象。

因此可以这里可以推测应该是进入后台做了什么操作导致,回到App刷新才会导致闪烁。

因为使用的是SDWebImage加载框架加载,我们合理的怀疑是加载图片的SDWebImage框架,进入后台的处理逻辑导致的,因此我们先使用imageCacheDict字典写下图片加载和缓存逻辑:

经测试,进入后台,再返回App刷新不会出现闪烁现象。

因此可以肯定UITableView调用reloadData方法闪烁原因是SDWebImage,在进入后台的时候对内存缓存做了相关操作导致。

我们都知道SDWebImage,默认是使用NSCache来做内存缓存,而NSCache在进入后台的时候,默认会清空缓存操作,导致返回App调用UITableView调用reloadData方法时候,SDWebImage需要根据图片地址重新去磁盘获取图像数据,然后解压解码渲染,因为是从缓存磁盘直接获取图像数据,没有渲染流程,因此会造成闪烁。

为了验证这个猜想,我们使用YYWebImage加载框架来做对比实验:

  • 首先注释掉YYWebImage进入后台清空内存缓存的逻辑:
  • 然后进入后台,返回App调用UITableView调用reloadData刷新,发现一切正常。

原因总结:

  • 第一个原因是UITableView调用reloadData方法,由于UITableViewCell的复用,会出现Cell位置调整现象

  • 由于SDWebImage使用了NSCache做内存缓存,当App进入后台,NSCache会清空内存缓存,导致返回App后调用UITableView调用reloadData,刷新去加载图片的时候,需要从SDWebImage的磁盘中重新获取图片数据,然后重新解压解码渲染,因为从磁盘中读取速度快,两者原因导致了闪烁。

三. 解决方案

因为该现象是由如上两个原因导致,因此针对这两个原因,有如下两种解决方案:

  • 解决UITableViewCell复用问题

可以通过设置ReusableCellWithIdentifier不同,保证广告cell不进行复用。

ini 复制代码
 NSString *cellId = [NSString stringWithFormat:@"%ld-%ld-FJFAdTableViewCell", indexPath.section, indexPath.row];
  • 从后台返回后,提早进行刷新操作

当从后台返回App前台的时候或者视图添加到父视图的时候,先执行下UITableView调用reloadData方法,提前通过SDWebImage去从磁盘中加载图片。

从后台返回前台:

objectivec 复制代码
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(willEnterForeground) name:UIApplicationWillEnterForegroundNotification object:nil];
- (void)willEnterForeground {
    [self.tableView reloadData];
    NSLog(@"--------------------------willEnterForeground");
}

视图添加到父视图:

objectivec 复制代码
- (void)willMoveToParentViewController:(UIViewController *)parent {
    [self.tableView reloadData];
}
相关推荐
li理2 分钟前
鸿蒙 Next 布局开发实战:6 大核心布局组件全解析
前端
EndingCoder3 分钟前
React 19 与 Next.js:利用最新 React 功能
前端·javascript·后端·react.js·前端框架·全栈·next.js
li理6 分钟前
鸿蒙 Next 布局大师课:从像素级控制到多端适配的实战指南
前端
前端赵哈哈10 分钟前
Vite 图片压缩的 4 种有效方法
前端·vue.js·vite
Nicholas6816 分钟前
flutter滚动视图之ScrollView源码解析(五)
前端
电商API大数据接口开发Cris18 分钟前
Go 语言并发采集淘宝商品数据:利用 API 实现高性能抓取
前端·数据挖掘·api
风中凌乱的L23 分钟前
vue 一键打包上传
前端·javascript·vue.js
GHOME27 分钟前
Vue2与Vue3响应式原理对比
前端·vue.js·面试
张元清30 分钟前
useMergedRefs: 组件封装必不可少的自定义Hook
前端·javascript·面试
openInula前端开源社区30 分钟前
【openInula茶话会】第四期:openInula API2.0编译器原理
前端·javascript