iOS 关键知识点iOS 优化

iOS安装包瘦身

2020-03-23  本文已影响0人  bluedaquiri

记录一次安装包大小优化的实践。
维持安装包体积是一个持续的过程,建立预警机制,监控每个版本的体积大小。

资源文件优化
图片资源优化
  1. 推荐通过FengNiao清理无用的图片资源 onevcat/FengNiao

FengNiao 的基本原理是查找出项目中所有使用到的字符串和项目中所有的资源文件,两者进行匹配(完全匹配和模式匹配,模式匹配支持带数字资源的前缀/中缀/后缀匹配),计算差集就为未使用的资源。

  1. 推荐通过ImageOptim进行图片压缩 ImageOptim

Xcode会自动压缩Assets内的PNG格式图片,但是Bundle内的图片资源仍需手动压缩。
对于三方库内的Bundle内的图片建议放置于Assets中。

  1. 大图优化
  1. 图标优化
  1. 推荐使用On-Demand Resources On-Demand Resources Guide

将 App 中的无需立即用到资源放在 App Store 云端上,然后你需要把资源标记为不同的Tag,需要的时候才去下载相应Tag的图片。如游戏中的不同关卡资源。

  1. 建议将webp作为项目图片格式
视频/音频资源远端化

建议将视频与音频文件放置在服务器,客户端按需下载或者使用流播放。

HTML5远端化

建议将HTML5资源放置在服务器,客户端可以使用离线缓存的方式来缓存网页资源到本地。


代码优化
  1. 扫描未使用代码

基本思路是基于 clang AST,追溯到函数的调用层级,记录所有定义的方法/类和所有调用的方法/类,再取差集。

基本思路是Mach-O 文件中的 (__DATA,__objc_classlist) 段表示所有定义的类, (__DATA.__objc_classrefs) 段表示所有引用的类(继承关系是在 __DATA.__objc_superrefs 中);使用的方法和引用的方法也是类似原理。因此我们使用 otool 等命令逆向可执行文件中引用到的类/方法和所有定义的类/方法,然后计算差集。

基本思路是对源码文件进行字符串匹配。例如将 A *a、[A xxx]、NSStringFromClass("A")、objc_getClass("A") 等归类为使用的类,@interface A : B 归类为定义的类,然后计算差集。

查找出 AppCode 中无用的类、无用的方法甚至是无用的 import ,但是无法扫描通过字符串拼接方式来创建的类和调用的方法。

  1. Cocoapods 中的优化选项配置

Cocoapods 的 project 文件在每次 pod install 或者 pod update 会重置,所以需要 hook pod install 来设置 Pods 中每个 Target 的编译选项:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['ENABLE_BITCODE'] = 'YES'
      config.build_settings['STRIP_INSTALLED_PRODUCT'] = 'YES'
      config.build_settings['SWIFT_COMPILATION_MODE'] = 'wholemodule'
      config.build_settings['SWIFT_VERSION'] = '5.0'
      if config.name == 'Debug'
        config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Onone'
        config.build_settings['GCC_OPTIMIZATION_LEVEL'] = '0'
        config.build_settings['COPY_PHASE_STRIP'] = 'NO'
        config.build_settings['DEPLOYMENT_POSTPROCESSING'] = 'NO'
        config.build_settings['GCC_GENERATE_DEBUGGING_SYMBOLS'] = 'YES'
      else
        config.build_settings['SWIFT_OPTIMIZATION_LEVEL'] = '-Osize'
        config.build_settings['GCC_OPTIMIZATION_LEVEL'] = 's'
        config.build_settings['COPY_PHASE_STRIP'] = 'YES'
        config.build_settings['DEPLOYMENT_POSTPROCESSING'] = 'YES'
        config.build_settings['GCC_GENERATE_DEBUGGING_SYMBOLS'] = 'NO'
      end
    end
  end
end
  1. 静态库瘦身

发布版本中删除 i386、x86_64 是模拟器的指令集,只保留 armv7 和 arm64

4.iOS的指令集

arm64:iPhone6s | iphone6s plus|iPhone6| iPhone6 plus|iPhone5S | iPad Air| iPad mini2(iPad mini with Retina Display)
armv7s:iPhone5|iPhone5C|iPad4(iPad with Retina Display)
armv7:iPhone4|iPhone4S|iPad|iPad2|iPad3(The New iPad)|iPad mini|iPod Touch 3G|iPod Touch4

i386是针对intel通用微处理器32位处理器
x86_64是针对x86架构的64位处理器

模拟器32位处理器测试需要i386架构,
模拟器64位处理器测试需要x86_64架构,
真机32位处理器需要armv7,或者armv7s架构,
真机64位处理器需要arm64架构。

编译优化
  1. Clang/LLVM 编译器优化选项
    Xcode ➡️ Build Setting ➡️Apple Clang - Code Generation ➡️ Optimization Level 设置为Fastest Smallest[-Os]
  1. Swift Compiler - Code Generation
    Xcode -> Build Setting ->Swift Compiler - Code Generation -> Optimization Level 设置为Optimize for Size[-Osize]
  1. Deployment
    Xcode ➡️ Build Setting ➡️ Deployment

在 Archive 的时候 Xcode 总是会把 Deployment Postprocessing 设置为 YES 。所以我们可以打开 Strip Linked Product 并且把 Deployment Postprocessing 设置为 NO,而不用担心调试的时候会影响断点和符号化,同时打包的时候又会自动去除符号信息。

与 Strip Linked Product 类似,但是这个是将那些拷贝进项目包的三方库、资源或者 Extension 的 Debug Symbol 去除掉,同样也是使用的 strip 命令。这个选项没有前置条件,所以我们只需要在 Release 模式下开启,不然就不能对三方库进行断点调试和符号化了

去掉不必要的符号信息,可以减少可执行文件大小,但去除了符号信息之后我们就只能使用 dSYM 来进行符号化。

  1. Link-Time Optimization
    Xcode ➡️ Build Setting ➡️Apple Clang - Code Generation ➡️Link-Time Optimization设置为Incremental

Link-Time Optimization 是 LLVM 编译器的一个特性,用于在 link 中间代码时,对全局代码进行优化。这个优化是自动完成的,因此不需要修改现有的代码;这个优化也是高效的,因为可以在全局视角下优化代码。
开启这个优化后,一方面减少了汇编代码的体积,一方面提高了代码的运行效率.

  1. Asset Catalog Compiler
    Xcode ➡️ Build Setting ➡️Asset Catalog Compiler ➡️Optimization设置为space

参考资料:
App Thinning in Xcode
网易云安装包瘦身
微信安装包瘦身
iOS 瘦身之道

上一篇下一篇

猜你喜欢

热点阅读