iOS 性能优化专题
iOS 性能优化全攻略
1. 渲染性能
离屏渲染
- 触发条件:圆角(masksToBounds)、阴影(shadow)、遮罩(mask)、光栅化
- 代价:GPU 需额外开辟缓冲区,切换上下文耗性能
- 优化:
- 圆角 → 用图片遮罩或 Core Graphics 画圆角背景
- 阴影 → 设置
shadowPath避免实时计算 - 静态内容 →
shouldRasterize = true(开启缓存,但内存增加)
卡顿检测
- CADisplayLink 监听帧率
- Instruments → Core Animation 查看 FPS 和离屏渲染
- RunLoop 观察者监测主线程超时(> 16ms 则记录堆栈)
2. 列表优化(UITableView / UICollectionView)
- Cell 复用:必须使用
dequeueReusableCell - 高度缓存:计算后缓存
heightForRow,避免重复计算 - 异步渲染:图片/富文本在子线程渲染,主线程只做展示(Texture/AsyncDisplayKit)
- 预计算:
prefetchDataSource在 cell 滚动到可视区前提前加载数据 - 图片下载:SDWebImage / Kingfisher 自带磁盘+内存缓存
3. 启动优化
冷启动阶段
pre-main 阶段 (dyld)
→ 加载动态库(减少动态库数量,合并/静态化)
→ Rebase / Binding(减少 ObjC 元数据:类/方法/分类)
→ Initializer(+load 方法,改用 +initialize 或 dispatch_once)
main() 之后
→ didFinishLaunching(延迟/异步初始化三方 SDK)
→ 首屏渲染
- 用
DYLD_PRINT_STATISTICS测量 pre-main 耗时 - 减少
+load方法(每个都在启动时执行) - 二进制重排(Clang 插桩 + 收集 order 文件)减少 Page Fault
4. 内存优化
- 图片内存:大图按需缩放,
UIImage(named:)会缓存,UIImage(contentsOfFile:)不缓存 - 循环引用排查:Instruments → Leaks / Allocations
- autoreleasepool:循环处理大量对象时手动加
@autoreleasepool {} - NSCache:系统内存紧张时自动清理,比 NSMutableDictionary 更合适
5. 网络优化
- HTTP/2:URLSession 默认支持,多路复用
- 请求合并:批量接口减少请求次数
- 图片格式:WebP / HEIF 替代 JPEG
- 离线缓存:URLCache + ETag / Last-Modified 协商缓存
- 压缩:Gzip / Brotli 压缩响应体
6. 包体积优化
- 资源优化:Asset Catalog 压缩,移除未使用资源(LSUnusedResources)
- 代码优化:
-dead_strip删除未引用代码 - 动态库转静态库:减少包体积和启动时间
- On-Demand Resources:按需下载资源,减少初始包大小
- App Thinning:Slicing(按设备分包)+ Bitcode
7. 高频面试题
- 界面卡顿的本质? 主线程 RunLoop 一次循环超过 16.7ms,帧率低于 60fps
- 为什么图片圆角会触发离屏渲染? 需要裁剪内容,必须在离屏缓冲区合成
- Instruments 如何定位内存泄漏? Leaks 工具 → 查看泄漏对象 → Allocation 追踪引用链
- 二进制重排原理? 通过收集启动期函数调用顺序写入 link map,让相关代码页相邻,减少 Page Fault