之前看过阿里UED的一篇文章“App瘦身记”,我来说一下我的经验。大致的思路是:分析Xcodebuild目录下xx.app的资源,按从大到小排序,重点优化大文件。
文/社区会员52doho
从09年开始做iPhoneDev到现在刚好3年时间,那个时候还在北京的一家公司实习,从OC语法开始自学,你可以看到周围的人在用iPhone3GS,但没人懂OC、很少人用过Mac系统。一路过来有cocoachina、stackoverflow、iphonedevsdk等出名站点的帮助,收获不少。现在,自己正处在角色的转型,对自己这3年来的iPhone开发在不停的思考着,整理成文档,希望自己的经验能够对CC朋友有所帮助。有错误的地方和任何问题,请毫不犹豫的指出。
这个帖子整理App大小优化的经验。
之前看过阿里UED的一篇文章“App瘦身记”,是从UED的角度来看待减小App大小,前面3点是建议,后面2点是瘦身办法。
我来说一下我的经验。大致的思路是:分析Xcodebuild目录下xx.app的资源,按从大到小排序,重点优化大文件。这个方法效果最好,能够让app瘦身50%以上,也就是减小用户一半的下载时间。
查看生成的app大小
Debug和Release编译模式产生的文件大小是不一样的,Debug模式生成的xx.app要大些。建议用Release模式生成的xx.app来分析,这个是最接近提交审核的IAP。
![](http://www.cocoachina.com/cms/uploads/allimg/120827/4064_120827155840_1.jpg)
产品上线后显示在AppStore上程序的大小是经过压缩的。可以手动压缩xx.app,查看生成的xx.zip的大小,这个是最接近产品上线后的大小。
![](http://www.cocoachina.com/cms/uploads/allimg/120827/4064_120827155855_1.jpg)
产品上线后iTunes显示的大小:
![](http://www.cocoachina.com/cms/uploads/allimg/120827/4064_120827155911_1.jpg)
开始瘦身
右键点击xx.app查看包的内容,按大小排序。
![](http://www.cocoachina.com/cms/uploads/allimg/120827/4064_120827155934_1.jpg)
![](http://www.cocoachina.com/cms/uploads/allimg/120827/4064_120827155944_1.jpg)
可以看到最占用空间的那些文件,一般是png文件占用的空间比较大,特别是iPad3视网膜的启动画面,可以大到7MB!如果app支持横竖屏,那么启动画面文件的大小又增加1倍。
这里列出常见的大文件:
1、可执行文件
2、启动画面 (比如:iPad 3 Retina)
3、背景图片
4、阿里UED里提到的Workthrough (这个在国内app很常见)
5、第三方库的bundle包、说明文件
6、音效素材 (比如:wav格式文件)
优化方法有:
1、不需要透明的地方,使用jpg而不是png。比如:背景图片、Workthrough、bundle里面的png文件,jpg压缩比使用0.6左右,在不影响视觉效果的情况下尽可能的小;
2、不使用Default.png,使用Default.jpg。苹果限制启动画面只能是png格式,iPad3 Retina的png文件往往都很大。这种情况下可以在app启动时显示Default.jpg,等到载入完毕后再显示首页。该方式的缺点是启动时会有黑屏然后才显示Default.jpg;优点是大大减小app大小,以及可自定义启动画面。比如UC浏览器HD在伦敦奥运会期间更换的启动画面;
3、素材做成可拉伸,类似Android的.9。界面导航条背景、弹框背景、按钮等都可以考虑用拉伸素材;
4、去除不必要的文件。一般开发时都有统一的通用库,方便其它工程调用,节省开发时间。把常用的库集成到通用库里会造成通用库体积变大,应该注意不必要的资源不要添加进去。比如:在发布的时候,TestFlight可以不用编译;第三方库的说明文件不要引入工程,Flurry的txt、pdf文件;如果付费版本不需要广告,那么广告SDK不要集成到通用库,只在单独的工程里引用;
5、优化png, jpg素材。推荐使用ImageOptim,在准备提交审核前,使用该工具优化所有png, jpg素材。可以减小~20%左右的图片大小。但png素材在Xcode编译后体积跟优化前的差不多,这个应该跟Xcode的优化方式有关;
6、音视频素材最好使用经过压缩的格式。wav的音频格式生成的文件比较大,可以使用苹果推荐的caf格式代替。关于如何选择音频压缩格式可以参考这篇文章:Audio101 for iPhone Developers: File and Data Formats。
在第一次产品提交审核前,可以过一下上面提到的方法,减小App大小。我们的一个产品PhotoCool 1.2版本的大小是22.4MB,在1.3版本使用以上方法进行优化,优化后只有13.1MB,缩小了41.5%!下载速度快了,用户会更高兴的。
文/社区会员52doho
续之前的“App再瘦身”。
这个帖子整理我遇到过的iPhone App Crash类型以及解决办法。Crash原因有很多,不同技术所导致的Crash会不同。整理出来的经验应该会相对片面,有错误的地方和任何问题,请毫不犹豫的指出。
保证App持续稳定运行是非常必要的,开发人员应该把维护产品稳定性、提高产品性能意识融入到每次编写代码过程当中,这也是很多公司考察优秀开发人员的一个重要环节。
Crash原因
Crash原因有共性,归纳起来有:
• 内存管理错误
• 程序逻辑错误
• SDK错误 (部署版本< 编译版本)
• 主线程阻塞
内存管理错误
内存管理是iPhone开发所要掌握的最基本问题,特别是使用引用计数手动管理内存的情况。内存管理错误包括:
• 内存泄漏:未释放不会再使用对象。比如alloc忘记release,malloc忘记free。可用XcodeProduct菜单下的Analyze功能来解决该问题;
• 引用出错:引用已经被释放的对象指针。很多“莫名其妙”的Crash都是由于窗体经历的生命周期所导致的(viewDidUnload、viewDidLoad),在iOSSimulator里模拟内存警告就可以解决该问题;
![](http://www.cocoachina.com/cms/uploads/allimg/120829/4064_120829114111_1.jpg)
• 内存警告:App使用的内存超出设备的限制,iOS将强制挂起App,强制挂起iOS是不会记录Crashlog,Flurry也无法记录。内存泄漏、快速/大量的分配内存都可能导致内存警告,这时候应该尽可能的释放不需要的资源。通过Instruments->Allocations里的Heapshot功能能够找出哪些资源未被释放。
![](http://www.cocoachina.com/cms/uploads/allimg/120829/4064_120829114203_1.jpg)
WWDC 2012的Session242 - iOS App Performance_ Memory是专门讨论内存管理这个话题。
程序逻辑错误
数组越界、堆栈溢出、并发操作、逻辑错误。扎实的编码基础、严谨细致的工作习惯、清晰的思路可以避免这类错误;
SDK错误
这个错误出现的现象是有的设备运行正常,有的会Crash。原因是未找到框架、类、方法、属性。比如:用iOS5.0 SDK编译并运行在iOS4.0的设备上,5.0的Twitter框架在4.0的设备上找不到。这种问题常出现在用苹果新发布的Xcode编译原有的工程。
未找到框架的解决办法是:部署版本>= 编译版本。iOS框架向后兼容做的很棒,部署版本> 编译版本一般不会出现问题。
未找到类、方法、属性的解决办法是:先判断是否存在再使用
if(NSClassFromString(@"MFMailComposeViewController"))
respondsToSelector:
主线程阻塞
主线程阻塞超过10s,iOS将强制挂起App。把长时间的任务放到后台线程去执行,可使用NSThread,NSOperation, dispatch。WWDC2012的Session235 - iOS App Performance_ Responsiveness有详细的介绍。
解决Crash
思路是:定位Crash的程序代码,预测Crash原因,寻找解决方案,测试。
有多种方式可以定位Crash的程序代码:
• Debug模式时,iOSSimulator断点测试定位Crash的堆栈;
• 真机连接iTunes查看Crashlog (Debug模式下);
• 通过Flurry的错误记录查看;
定位之后,就是重新思考程序上下文逻辑,并有理由的预测Crash出现的原因。预测的越多,理解的越深。
寻找解决方案的方法有:
• 浏览苹果官方SDK文档,找出错误原因;
• Google搜索Crash输出的信息,重点查找行业内技术论坛:cocoachina、stackoverflow、iphonedevsdk等;
• 查看历届WWDC的视频、示例代码;
• 在工程里添加环境变量: NSZombieEnabled、NSDebugEnabled,输出有价值的信息;
• 如果未找到任何信息,可以寻求苹果官方论坛、业内技术论坛的帮助;
测试
找到解决方案后就需要测试,测试功能输入输出的准确性、程序性能、是否引入新的bug。测试有专业的测试工程师来负责,但开发工程师不能依赖测试工程师来发现问题,尽量独立解决已知存在的问题。
由于Xcode部署工程到真机上比较耗时间,如果可以的话尽可能用iOSSimulator来测试,以减少测试的时间。
建议开发工程师有一个checklist,在产品测试时自己逐一过一下上面常见的问题,这个能够避免大部分Crash。下图是我们一个产品的FlurryError记录,那120个错误Session是测试Crash时留下的。当然这个记录是没有包括iOS将强制挂起App的情况。
![](http://www.cocoachina.com/cms/uploads/allimg/120829/4064_120829114229_1.jpg)