性能优化的核心目标是:启动快、滑动顺、内存省、耗电低。
1. 启动速度优化 (Launch Time)
启动分为冷启动(App从零开始)和热启动(后台切回)。面试官通常关注冷启动。
核心原理:冷启动主要耗时在 dyld (动态库加载) -> Runtime (ObjC类注册/方法交换) -> main() -> didFinishLaunching。
优化策略:
- 减少动态库:每个动态库加载会增加 6~8ms,且增加缺页中断。尽量合并动态库或使用静态库。
-
主线程瘦身:将
didFinishLaunching中的非核心业务(如日志初始化、非必要的统计SDK)延迟到主线程空闲时执行,或放入子线程。 -
二进制重排:通过插桩收集启动时的函数调用顺序,生成
.order文件,指导编译器将启动代码紧凑排列,减少缺页中断(Page Fault),可提升 50%+ 的启动速度。 - 预加载:在启动时预加载首屏需要的关键资源(如图片解码),避免首屏渲染时卡顿。
2. 渲染与卡顿优化 (Rendering & Stutter)
目标是保持 60 FPS,即每帧耗时控制在 16.67ms 以内。
CPU 瓶颈
-
对象创建与销毁:避免在
cellForRowAt等高频调用方法中创建临时对象。 - 布局计算:AutoLayout 虽然方便,但计算成本高。对于复杂且固定的布局,可直接计算 frame。
- 文本处理:字符串计算、JSON 解析应移至后台线程。
GPU 瓶颈
-
离屏渲染 (Offscreen Rendering):这是高频考点。
-
触发条件:设置
cornerRadius + masksToBounds、shadow、layer.mask等。 - 代价:需要创建新缓冲区,且涉及上下文切换(Context Switch),非常消耗性能。
-
解决:圆角尽量用贝塞尔路径绘制或使用 CAShapeLayer;阴影可用一张透明图片代替或设置
shadowPath。
-
触发条件:设置
-
过度绘制 (Overdraw):避免视图层级过深,移除看不见的背景视图(如
backgroundColor = .clear会导致混合渲染,尽量设为不透明)。
列表优化
- Cell 复用:确保复用机制正常工作。
- 异步绘制:使用 Texture (AsyncDisplayKit) 或在子线程进行图片解码和文本测量,主线程只做最终渲染。
3. 内存优化 (Memory)
-
图片缓存:
UIImage(named:)会缓存到系统内存中且不易释放,适合小图标;大图加载建议使用imageWithContentsOfFile:并配合 SDWebImage 或 Kingfisher 的内存/磁盘缓存策略。 -
循环引用:Block、Timer、Delegate 是重灾区。务必使用
[weak self]或unowned破环。 - 检测工具:熟练使用 Xcode 的 Memory Graph 查看引用链,使用 Leaks 检测内存泄漏。
4. 包体积瘦身 (App Thinning)
- 资源压缩:使用 TinyPNG 等工具压缩图片,删除未使用的资源(利用 Xcode 的 Report Navigator 或第三方工具如 LSUnusedResources)。
- 代码剥离:开启编译优化,移除无用代码。
- 动态库/静态库:合理选择库的类型,静态库在链接时会被合并,动态库会增加包体积和加载时间。