跳到主要内容

UI 卡顿排查

问题

App 滑动列表时卡顿掉帧,如何排查和优化?

答案

排查步骤

常见原因及优化

原因排查方式优化方案
离屏渲染模拟器 → Color Off-screen Rendered避免 cornerRadius + masksToBounds
图片解码Time Profiler 看 CGImageSourceCreateImageAtIndex后台线程预解码
AutoLayout 嵌套过深Layout 阶段耗时减少嵌套或用手动布局
透明混合Color Blended Layers设置 isOpaque = true,避免透明背景
主线程 I/O主线程出现文件/数据库调用移到后台线程

离屏渲染优化

// ❌ 触发离屏渲染
imageView.layer.cornerRadius = 8
imageView.layer.masksToBounds = true

// ✅ 方案一:使用 CAShapeLayer 遮罩
let mask = CAShapeLayer()
mask.path = UIBezierPath(roundedRect: imageView.bounds, cornerRadius: 8).cgPath
imageView.layer.mask = mask

// ✅ 方案二:后台线程绘制圆角图片
extension UIImage {
func roundedImage(radius: CGFloat) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { ctx in
UIBezierPath(roundedRect: CGRect(origin: .zero, size: size), cornerRadius: radius).addClip()
draw(in: CGRect(origin: .zero, size: size))
}
}
}

常见面试问题

Q1: 如何在线上检测卡顿?

答案:子线程定时向主线程发信号量,如果超时(>50ms)说明主线程阻塞。此时采集主线程调用栈上报。这是 卡顿监控 的核心原理。

相关链接