众所周知,在App Store中超过一定大小的文件只能使用WiFi下载(近期提升到了150M,之前是100M)。虽然提升了一点,但是我们仍需要注意安装包的大小。毕竟除了游戏很少有人喜欢下很大的应用。
那么如何知道是哪些文件占得空间比较大呢?有一个比较简单的方法就是找到IPA包,解压得到.app文件,显示包内容,就可以查看到里面的东西了。
*注意:.app bundle是经过压缩的,并且有些文件的压缩效果要比别的文件好,所以压缩后的效果才是才是最重要的。不过一般情况下在压缩前最大的文件,在压缩后依旧是最大的文件。我们可以将某个文件删除,然后在Finder中右键单击,选择压缩,这样可以更加精确的测量文件压缩效果。
bundle如果你不懂的话可以查看这篇文章。参考
看到这里我们就知道一个ipa里面大文件都有哪些了,然后就可以针对性的修改。
说了上面一些,下面开始说一些干货吧。
首先是Xcode编译选项优化。经过下面这些设置,你的APP就会小很多。
Xcode编译选项优化方法:
1.舍弃架构armv7
armv7用于支持4s和4,4s是2011年11月正式上线,虽然还有小部分人在使用,但是追求包体大小的完全可以舍弃了。
2.冗余代码剥离
build setting 里 DEAD_CODE_STRIPPING = YES(好像默认就是YES)。 确定 dead code(代码被定义但从未被调用)被剥离,去掉冗余的代码,即使一点冗余代码,编译后体积也是很可观的。
![](https://i-blog.csdnimg.cn/blog_migrate/021a80b9ed43ce9ebead534fe10b4dbb.png)
3.编译器优化级别
Build Settings->Optimization Level有几个编译优化选项,release版应该选择Fastest, Smalllest[-Os],这个选项会开启那些不增加代码大小的全部优化,并让可执行文件尽可能小。
4.配置编译选项
(Levels选项内)Generate Debug Symbols 设置为NO,这个配置选项应该会让你减去小半的体积。注意这个如果设置成NO就不会在断点处停下
5.去除符号信息
Strip Debug Symbols During Copy 和 Symbols Hidden by Default 在release版本应该设为yes,可以去除不必要的调试符号。Symbols Hidden by Default会把所有符号都定义成”private extern”,设了后会减小体积。
6.Strip Linked Product:DEBUG下设为NO,RELEASE下设为YES,用于RELEASE模式下缩减app的大小;
7.编译器优化,去掉异常支持。Enable C++ Exceptions、Enable Objective-C Exceptions设置为NO,Other C Flags添加-fno-exceptions
接下来就是资源文件了,这些都是占大头的。
在开发中我们会使用一些本地图片,本地资源,三方SDK之类的。这些东西会占用很大的内存。下面我会一一解决。
1.本地资源文件
一些大图片或者音视频我们不会设置成网络,而是存储在本地,这就导致的IPA包的加大。
精简本地资源文件方法:
(1)压缩资源文件,如使用 ImageOptim 或者 TinyPng 来压缩图片,还可以在调整一下音视频的码率,减小体积;
(2)把一些资源放在网络上,如一些非第一时间加载需要的资源文件(需要根据不同业务逻辑进行判断)放置在网络上,在加载完成后静默下载存储在本地。留存之后使用。
(3)简单的图片可以使用代码自动生成。很类似的图片,仅仅只有颜色不同,可以通过代码处理图片的颜色。
(4)Xcode 中也会有一些图片相关设置,Compress PNG Files 和 Remove Text Medadata From PNG Files。前者打包的时候自动对图片进行无损压缩,后者会移除 PNG 图像名称、作者、版权、创作时间、注释等信息。
1 -(UIImage*)imageChangeColor:(UIColor*)color{ 2 UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0f);//获取画布 3 [color setFill];//画笔沾取颜色 4 CGRect bounds = CGRectMake(0, 0, self.size.width, self.size.height); 5 UIRectFill(bounds); 6 [self drawInRect:bounds blendMode:kCGBlendModeOverlay alpha:1.0f];//绘制一次 7 [self drawInRect:bounds blendMode:kCGBlendModeDestinationIn alpha:1.0f];//再绘制一次 8 UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); 9 UIGraphicsEndImageContext();//获取图片 10 return img; 11 } 12 13 + (UIImage *)getLaunchImage{ 14 CGSize viewSize = [UIScreen mainScreen].bounds.size; 15 NSString *viewOr = @"Portrait";//垂直 16 NSString *launchImage = nil; 17 NSArray *launchImages = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"]; 18 for (NSDictionary *dict in launchImages) { 19 CGSize imageSize = CGSizeFromString(dict[@"UILaunchImageSize"]); 20 if (CGSizeEqualToSize(viewSize, imageSize) && [viewOr isEqualToString:dict[@"UILaunchImageOrientation"]]) { 21 launchImage = dict[@"UILaunchImageName"]; 22 } 23 } 24 return [UIImage imageNamed:launchImage]; 25 }
补充:
音频的压缩参考WWDC中的Audio Development for Games,里面介绍了如何有效的处理音频。常规来说,我们要使用AAC或MP3来压缩音频,并且可以尝试降低一下音频的比特率。有时候44.1khz的采样是没有必要的,稍微低一点的比特率也不会降低音频的质量。
图片方面尽量使用8-bit图片(使用8-bit的PNG图片会比32-bit的图片能减少4倍的压缩率。但是8-bit的图片支持最多256种不同的颜色,所以8-bit的图片一般只应该用于一小部分的颜色图片。例如灰度图片最好使用8-bit。)针对32-bitt的图片尽量使用高压缩的比率:利用Adobe Photoshop的Save For Web可以减小JPEG和PNG的图片大小。在Xcode中,默认情况下,会自动的使用pngcrush来压缩.png图片。
2.Assets.xcassets里的图片
在版本迭代中我们也会遇到一下界面调整,图片更换的情况,尤其是在一些活动或者主题色变化时,经常会往里面添加新图片,一些老图片可能就不会删除,久而久之,图片大小就越来越大。
精简图片的方法:
(1)使用在线压缩png图片网站来压缩图片:compresspng或tinypng
(2)一些比较大体积的背景图片压缩成.jpg格式的。
(3)删除无用图片
用LSUnusedResource这个软件查找项目中没有用到的图片,然后删除,当然不一定特别准确,有一些[UIImage imageNamed:[NSString stringWithFormat:@"icon_%d",index]]这样使用的图片也会被列在未使用图片中。
也可以使用这个脚本工具可以大范围检测程序中没有用到的图片http://blog.csdn.net/songhongri/article/details/21833069
使用方法:1.将.sh文件放到所检测工程的目录下,
2.cd到该目录下,
3.执行脚本:sh unusedImage.sh
注意:这里在删除未应用的图片时注意第三方库里的不能删除,保险起见相同文件夹下的最好在工程里手动再搜索一次,确定没有使用到,就可以删除了。
3.SDK
我之前开发中遇到的一个APP,内容较多功能比较复杂,SDK就有将近200m,虽然知道App Store会有压缩,可是还是很大,这是我们就需要精简SDK了。
精简SDK方法:
(1)最基本的就是去除无用的SDK
(2)尽量使用同一个公司下的SDK,我之前就见过一个开发分享用shareSDK,统计用的友盟,bug分析用的buggly。还有其他的SDK,基本就是一个功能用一套,这不就是很大的问题吗?在国内公司基本上都是往全的方向做,一个完整的SDK基本上就能包含大部分功能了,所以使用同一个公司的内容,缺失再补充SDK就是一个很好的方法
(3)在使用SDK的时候,我们不需要下载全部的功能,我们可以选择性下载功能,用不到的功能我们不需要下载。
4.代码
代码方面也有很多需要注意的地方,如一些readme文件和一些迭代中产生的无效代码等。
精简代码的方法:
(1)将数据从代码中剥离出来
将所有的资源(例如很长的字符串)从代码中剥离出来,并存入外部文件,这样会减小最终文件下载的大小,因为这些文件的压缩效果更好。(参考iOS App Store Specific Considerations中的完整介绍。)
(2)无用代码的删除
通过 AppCode 打开对应的工程文件 选择 Code -> inspect Code 分析代码,去掉无用的引用及代码。查找内部使用到的第三方库,一方面可以进行删减代码,用不到的类,可以直接删除,还有把第三方库中的图片资源删除掉。
(3)一些文档的替换
在开发中我们可能会有一些文档之类的在代码中,但是在迭代后可能会没有用,我们可以删除这些东西来减小体积。