编译选项

1.编译器优化级别

Build Settings->Optimization Level有几个编译优化选项,release版应该选择Fastest, Smalllest,这个选项会开启那些不增加代码大小的全部优化,并让可执行文件尽可能小。

2.去除符号信息

Strip Linked Product / Deployment Postprocessing / Symbols Hidden by Default 在release版本应该设为yes,可以去除不必要的调试符号。Symbols Hidden by Default会把所有符号都定义成”private extern”,详细信息见官方文档(https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/MachOTopics/1-Articles/executing_files.html#//apple_ref/doc/uid/TP40001829-97021-TPXREF121)。

这些选项目前都是XCode里release的默认选项,但旧版XCode生成的项目可能不是,可以检查一下。

第三方库统计

项目里会引入很多第三方静态库,如果能知道这些第三方库在可执行文件里占用的大小,就可以评估是否值得去找替代方案去掉这个第三方库。我们可以从linkmap中统计出这个信息,对此写了个node.js脚本,可以通过linkmap统计每个.o目标文件占用的体积和每个.a静态库占用的体积。

ARC->MRC

有人提出用ARC写的代码编译出来的可执行文件是会比用MRC大的,原因大致是ARC代码会在某些情况多出一些retain和release的指令,例如调用一个方法,它返回的对象会被retain,退出作用域后会被release,MRC就不需要,汇编指令变多,机器码变多,可执行文件就变大了。还有其他细节实现的区别,先不纠结了。

那用ARC究竟会增大多少体积?我觉得从汇编指令的增多减少去算是很难算准确的,这东西涉及细节太多,还是得从统计的角度计算。做了几个对比试验,统计了几个同时支持ARC/MRC的开源项目在开启/关闭ARC的情况下__TEXT代码段的大小对比。只对比__TEXT代码段是因为:

1、ARC对可执行文件大小的影响几乎都是在代码段;

2、可执行文件会进行某种对齐,例如有些段在不足32K的时候填充0直到对齐32K,若用可执行文件大小对比结果可能是对齐后的,不准确。

无用代码

在项目里新建一个类,给它添加几个方法,但不要在任何地方import它,build完项目后观察linkmap,你会发现这个类还是被编译进可执行文件了。

按C++的经验,没有被使用到的类和方法编译器都会优化掉,不会编进最终的可执行文件,但object-c不一样,因为object-c的动态特性,它可以通过类和方法名反射获得这个类和方法进行调用,所以就算在代码里某个类没被使用到,编译器也没法保证这个类不会在运行时通过反射去调用,所以只要是在项目里的文件,无论是否又被使用到都会被编译进可执行文件。

对此我们可以通过脚本,遍历整个项目的文件,找出所有没有被引用的类文件和没有被调用的方法,在保证没有其他地方动态调用的情况下把它们去掉。如果整个项目历时很长,历时代码遗留较多,这个清理对可执行文件省出的空间还是挺可观的。

类/方法名长度

观察linkmap可以发现每个类和方法名都在__cstring段里都存了相应的字符串值,所以类和方法名的长短也是对可执行文件大小是有影响的,原因还是object-c的动态特性,因为需要通过类/方法名反射找到这个类/方法进行调用,object-c对象模型会把类/方法名字符串都保存下来。

对此我们可以考虑在编译前把所有类和方法名进行混淆,跟压缩js一样,把长名字替换成短名字,这样做的好处除了缩小体积外,还对安全性有很大提升,别人拿到可执行文件对它class-dump出来的结果都是混淆后的类和方法名,就无法从类和方法名中猜出某个方法是做什么的,就难以挂钩子进行hack。不过这样做有个缺点,就是crash堆栈反解出来的堆栈方法名会是混淆后的,需要再加一层混淆->原名的转换,实现和使用成本有点高。

实际上这部分占用的长度比较小,中型项目也就几百K,对安全性要求高的情况可以试试。

冗余字符串

代码上定义的所有静态字符串都会记录在在可执行文件的__cstring段,如果项目里Log非常多,这个空间占用也是可观的,也有几百K的大小,可以考虑清理所有冗余的字符串。另外如果有特别长的字符串,建议抽离保存成静态文件,因为AppStore对可执行文件加密导致压缩率低,特别长的字符串抽离成静态资源文件后压缩率会比在可执行文件里高很多。

CheckList

最后把缩减iOS安装包大小的各种方法列出来做了张CheckList图:

iOS 可执行文件瘦身方法的更多相关文章

  1. iOS可执行文件瘦身方法

    缩减iOS安装包大小是很多中大型APP都要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源.这些资源优化做完后,我们还可以尝试对可执行文件进行瘦身,项目越大,可执行文件占用的体积越大 ...

  2. 【转】iOS可执行文件瘦身方法

    http://blog.cnbang.net/tech/2544/ 缩减iOS安装包大小是很多中大型APP都要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源.这些资源优化做完后,我 ...

  3. iOS代码瘦身实践

    1 分析当前ipa的组成 一般一个ipa会包含: 1) 资源文件 本地文件:数据.配置.数据库等等 字体文件 图片资源 2)  源代码 通过生成linkmap文件,分析源代码生成的编译文件的大小.在B ...

  4. iOS App 瘦身方案

    缩减iOS安装包大小是很多中大型APP都要做的事,一般首先会对资源文件下手,压缩图片/音频,去除不必要的资源.这些资源优化做完后,我们还可以尝试对可执行文件进行瘦身,项目越大,可执行文件占用的体积越大 ...

  5. iOS图片瘦身总结

    前言 最近在公司写了个小程序来为iOS应用中的图片瘦身,进而减小APP大小,减少用户下载时的流量. 瘦身是在一个专门为图片瘦身的网站进行的. 地址:https://tinypng.com 这个网站提供 ...

  6. iOS控制器瘦身-面向超类编程

    今天写这篇文章的目的,是提供一种思路,来帮助大家解决控制器非常臃肿的问题,对控制器瘦身. 滴滴 老司机要开车了 如果手边有项目,不妨打开工程看一下你的控制器代码有多少行,是不是非常多?再看一下tabl ...

  7. golang可执行文件瘦身(缩小文件大小)

    起因 golang部署起来极其遍历,但有时候希望对可执行文件进行瘦身(缩小文件大小) 尝试 情况允许情况下,交叉编译为32位 删除不必要的符号表.调试信息 尝试用对应平台的upx打压缩壳 解决 经过多 ...

  8. iOS ViewControllers 瘦身

    https://objccn.io/issue-1-1/ https://juejin.im/user/57ddfba4128fe10064cbb93a 把 Data Source 和其他 Proto ...

  9. Android APK瘦身方法小结

    众所周知,APP包体的大小,会影响推广的难度,用户不太喜欢下载太大的APP,同类型同等功能的APP中往往是包体小的更受用户的青睐,所以降低包体是一项非常必要的事情,也是最近公司的APP需要降低包体,所 ...

随机推荐

  1. AD域的安装(在Windows Server 2003中安装Active Directory)

    在Active Directory中提供了一组服务器作为身份验证服务器或登录服务器,这类服务器被称作域控制器(Domain Controller,简称DC).建立一个AD域的过程实际就是在一台运行Wi ...

  2. maven 配置问题

    ① 错误 Cannot load JDBC driver class 'oracle.jdbc.driver.OracleDriver' 原因:pom.xml文件下载ojdbc14-10.2.0.3. ...

  3. Activity系列讲解---Activity运行时的屏幕方向,全屏,窗体模式的设置

    Android内置了方向感应器的支持.Android会根据所处的方向自动在竖屏与横屏间切换.但是有的应用程序只能在横/竖屏时运行,比如某些游戏,此时我们要锁定该Activity运行时的屏幕方向,< ...

  4. Excel2013 基本用法(上)

    自动填充 对于数字填充 Excel对于处理数据非常方便,比如我们需要输入一个班级的学号,就可以只输入2个学号然后快捷填充就可以完成一个班的学号输入(如下图). 快捷填充,就是将鼠标移动到选中的单元格边 ...

  5. Mysql学习笔记(附一)

    关于外键约束关系下修改或者删除表的方法: http://wenku.baidu.com/link?url=RRaI160kvsdf7ibMLqxN815RvStSyenz_-ig1ONfpRfpfFp ...

  6. Mybatis批量操作

    首先,mysql需要数据库连接配置&allowMultiQueries=true jdbc:mysql://127.0.0.1:3306/mybank?useUnicode=true& ...

  7. STL源码学习----lower_bound和upper_bound算法

    转自:http://www.cnblogs.com/cobbliu/archive/2012/05/21/2512249.html 先贴一下自己的二分代码: #include <cstdio&g ...

  8. [转]utf8编码原理详解

    from : http://blog.csdn.net/baixiaoshi/article/details/40786503 很久很久以前,有一群人,他们决定用8个可以开合的晶体管来组合成不同的状态 ...

  9. Jquery-zTree的用法

    [部分函数和属性介绍] 核心:zTree(setting, [zTreeNodes]) 这个函数接受一个JSON格式的数据对象setting和一个JSON格式的数据对象zTreeNodes,从而建立 ...

  10. zsh 命令提示符 PROMPT

    使用上zsh后,发现命令提示符显示不了当前的路径,和一般的Linux系统默认提示不一致.配置自己的提示符: 更改配置文件.zshrc,添加配置PROMPT='%m:%. $',重新打开一个窗口生效. ...