UITableView垂直滚动卡顿求助:SDWebImage回调中处理圆角图片所致
UITableView滚动卡顿优化:图片圆角处理方案
问题描述
在UITableViewCell中使用SDWebImage下载图片,下载完成的回调block内调用自定义circularImage方法处理圆角,导致UITableView垂直滚动时出现卡顿。请问是否需要通过GCD调度解决该问题以实现流畅滚动?
相关代码
自定义圆角处理方法:
func circularImage(size: CGSize?) -> UIImage? { let newSize = size ?? self.size let minEdge = min(newSize.height, newSize.width) let size = CGSize(width: minEdge, height: minEdge) UIGraphicsBeginImageContextWithOptions(size, false, 0.0) let context = UIGraphicsGetCurrentContext() self.draw(in: CGRect(origin: CGPoint.zero, size: size), blendMode: .copy, alpha: 1.0) context?.setBlendMode(.copy) context?.setFillColor(UIColor.clear.cgColor) let rectPath = UIBezierPath(rect: CGRect(origin: CGPoint.zero, size: size)) let circlePath = UIBezierPath(ovalIn: CGRect(origin: CGPoint.zero, size: size)) rectPath.append(circlePath) rectPath.usesEvenOddFillRule = true rectPath.fill() let result = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() return result }
UITableViewCell内代码:
if let thumbImageUrlUW = valueUW.thumbImageUrl { UIImageView().sd_setImage(with: URL(string: thumbImageUrlUW)) { (thumbImage, _, _, _) in if let thumbImageUW = thumbImage, let roundedThumbImage = thumbImageUW.circularImage(size: imageSize) { valueUW.thumbImage = roundedThumbImage colorsUW.remove(at: index) colorsUW.insert(valueUW, at: index) } } }
界面截图


问题分析
卡顿的核心原因是图片圆角处理操作在主线程执行:circularImage方法中的图形绘制(如UIGraphicsBeginImageContextWithOptions、路径绘制等)属于CPU密集型操作,会阻塞主线程的UI刷新,导致UITableView滚动时掉帧卡顿。
优化方案
1. 用GCD将图片处理移到后台线程
SDWebImage的默认回调在主线程执行,需要把circularImage的调用放到后台队列,处理完成后切回主线程更新UI和数据,避免阻塞主线程。
修改后的Cell代码:
if let thumbImageUrlUW = valueUW.thumbImageUrl { UIImageView().sd_setImage(with: URL(string: thumbImageUrlUW)) { (thumbImage, _, _, _) in guard let thumbImageUW = thumbImage else { return } // 后台线程执行图片圆角处理 DispatchQueue.global().async { if let roundedThumbImage = thumbImageUW.circularImage(size: imageSize) { // 切回主线程更新数据和UI DispatchQueue.main.async { valueUW.thumbImage = roundedThumbImage // 直接修改数据源对应项,无需remove+insert colorsUW[index] = valueUW // 刷新对应cell,保证UI同步 self.tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic) } } } } }
2. 更高效的圆角处理替代方案
自定义图形绘制的效率并非最优,推荐以下两种更适合UITableView场景的方案:
方案A:使用SDWebImage自带的图片处理器
SDWebImage内置SDImageRoundCornerTransformer,可以在下载阶段直接处理圆角,内部已做好线程优化,无需自己编写绘制代码:
// 创建圆形图片处理器(圆角半径设为图片边长的一半) let transformer = SDImageRoundCornerTransformer( cornerRadius: imageSize.width / 2, corners: .allCorners, borderWidth: 0, borderColor: nil ) if let thumbImageUrlUW = valueUW.thumbImageUrl { UIImageView().sd_setImage( with: URL(string: thumbImageUrlUW), placeholderImage: nil, context: [.imageTransformer: transformer] ) { (thumbImage, _, _, _) in if let thumbImageUW = thumbImage { valueUW.thumbImage = thumbImageUW colorsUW[index] = valueUW self.tableView.reloadRows(at: [IndexPath(row: index, section: 0)], with: .automatic) } } }
方案B:直接给UIImageView设置Layer圆角
如果图片尺寸固定,直接对UIImageView的Layer设置圆角,性能开销远低于修改图片本身,还能避免重复绘制:
// 在Cell的初始化或配置方法中设置 imageView.layer.cornerRadius = imageSize.width / 2 imageView.layer.masksToBounds = true // 开启光栅化优化性能 imageView.layer.shouldRasterize = true imageView.layer.rasterizationScale = UIScreen.main.scale
这种方式无需在SDWebImage回调中处理图片,只需配置视图属性即可,是UITableView场景下最轻量化的圆角实现方式。
3. 额外优化建议
- 避免在回调中使用
remove(at:)+insert(at:)修改数组,直接修改对应索引的元素即可,减少数组操作开销。 - 给UIImageView设置占位图,提升滚动时的视觉体验,避免空白闪烁。
内容的提问来源于stack exchange,提问作者Ram
相关产品推荐
相关产品推荐

