UITableView滚动卡顿迟缓,如何优化Cell内图片缩放处理逻辑?
性能问题根源
你现有代码的卡顿来自三个严重的错误逻辑:
- 用
NSData(contentsOf: mediaUrl)在主线程同步发起网络请求,这个API会直接阻塞当前线程直到网络请求返回,滚动时频繁调用必然卡死 - 已经调用SDWebImage的
sd_setImage加载了一次媒体图片,后面又重复发起了一次同URL的网络请求,双倍浪费网络和CPU资源 - 图片缩放计算完全放在主线程执行,大量并发计算直接抢占UI渲染资源
优化后的代码实现
直接复用SDWebImage的加载能力,不需要自己处理网络请求,两种实现方案可选:
方案1:用SDWebImage自带的缩放工具(推荐)
自带缩放能力会自动缓存处理后的图片,下次加载同尺寸的同URL图片不需要重复计算,性能最优:
func set(post:Posts) { self.post = post // 加载头像逻辑不变 let url = post.url profileImageView.sd_setImage(with: url, completed: nil) // 加载并自动缩放媒体图片 let mediaUrl = post.urlM let targetWidth = MediaPhoto.frame.width // 按宽度等比缩放,高度自适应 let scaleTransformer = SDImageResizingTransformer(size: CGSize(width: targetWidth, height: CGFloat.greatestFiniteMagnitude), scaleMode: .aspectFit) MediaPhoto.sd_setImage(with: mediaUrl, placeholderImage: nil, context: [.imageTransformer: scaleTransformer]) }
方案2:自定义缩放逻辑
如果需要定制特殊缩放规则,把缩放逻辑扔到异步线程执行,不阻塞主线程:
func set(post:Posts) { self.post = post let url = post.url profileImageView.sd_setImage(with: url, completed: nil) let mediaUrl = post.urlM let targetWidth = MediaPhoto.frame.width MediaPhoto.sd_setImage(with: mediaUrl) { [weak self] image, _, _, _ in guard let self = self, let image = image else { return } // 异步执行缩放逻辑,不抢占UI线程资源 DispatchQueue.global(qos: .userInitiated).async { let scale = targetWidth / image.size.width let newHeight = image.size.height * scale let renderSize = CGSize(width: targetWidth, height: newHeight) // 用更高效的UIGraphicsImageRenderer替代旧的上下文API let renderer = UIGraphicsImageRenderer(size: renderSize) let scaledImage = renderer.image { _ in image.draw(in: CGRect(origin: .zero, size: renderSize)) } // 回到主线程赋值图片 DispatchQueue.main.async { self.MediaPhoto.image = scaledImage } } } }
额外优化建议
- 提前计算好每个cell里媒体图片的高度,存入UITableView的高度缓存,不要等图片加载完再算高度,避免滚动时反复重算布局
- 如果后台接口会返回图片的原始宽高比,可以直接用返回的比例提前算好控件高度,完全不需要等图片下载完成再做计算,滚动流畅度会更高
内容的提问来源于stack exchange,提问作者CodingForFun333
相关产品推荐
相关产品推荐

