iOS项目的瘦身与加快编译速度
随着开发的不断进行,我们的项目总会变得越来越大,而过大的占用用户的内存空间会对用户的留存造成一定的影响,所以我们总是需要找到方案来减小我们的包大小。在我们努力的同时苹果也在为此努力着,下文的第一部分主要介绍的就是官方文档和个人经验总结出的一些关于包瘦身的方案。此外项目变大后,我们在开发时每次启动程序的编译时间都会变长,这对于开发者而言是效率极低的一件事,文章的第二部分主要介绍如何在编译速度的角度去优化程序。
项目瘦身
-
切面(Slicing)
这一功能是苹果在 iOS 9 、watchOS 2 、tvOS 中推出的新功能,不需要我们进行任何的设置就可以完成,这个功能的主要作用在于对于不同的设备可以下发根据当前设备的CPU架构的可执行文件和资源文件。所以当用户在下载APP的时候就会进行匹配,而不会向之前一样下载针对所有设备的架构文件了,这样就变相的帮助我们减小了包体积。
-
Bitcode
这一功能同样是在 iOS 9 之后推出,可以在 Xcode 7 以上版本中在 Build Setting -> Enable Bitcode ( ENABLE_BITCODE ) 先完成对应的设置。这样做的好处在于官方会自动的帮我们去做一些优化,查看了一些国外的文章大致的猜想是苹果在设备安装应用的时候,会根据设备的 CPU 架构自动的去下发与架构相匹配的一份二进制文件,而生成的其它 CPU 架构的二进制文件则不被下发。这样就可以让我们的包体积大大减小,我们的项目可能会在 iphone4s 、 iphones 5 、iphone 6 上进行使用。如果我们用 iphone6 去下载,那么只会给我们一份 arm 64 架构下编译文件,而不会在下载 armv 7 和 armv 7s下的编译文件。这样对我们包体积的优化还是很有必要的。
Bitcode 相关文章链接(自备梯子) -
资源文件下载
我们一般在开发过程中遇到的一些界面UI图片都是放在本地的Asserts文件夹中的,所以随着项目的扩充,我们可能会有非常多的资源文件,而此时包体积会变得非常的大。为了解决这一问题,苹果在 iOS 9 中同样提出了对应的解决方案。我们可以把一些不常用的界面的 UI 存储在苹果的服务器上,第一次进入界面的时候,会去服务器加载相关的图片,然后将图片下载到本地,下次进入该页面会从本地读取资源文件。这样的方案听起来为我们解决了包体积过大的问题。
但是这样的解决方案有如下的缺陷。
-
这一项功能也是在 iOS 9 之后的设备上才能够被使用,也就是说我们的项目如果支持 iOS 8 及以下的设备还是没有办法完成。
-
这一功能下载的资源文件虽然存储在本地,但是如果用户的设备磁盘空间不足的时候,系统会优先清空这一部分内存,也就是说用户可能对于这些资源需要下载多次。
-
因为是从苹果服务器上拉取资源文件,所以肯定要考虑网络环境的问题,如果网络环境不好的情况下,这样的方法对于用户体验是不友好的。
-
实战方案
-
其实相比于我们的代码,比较占内存的还是资源文件,所以除了优化本地代码结构,更好的封装删除无用代码之外,最主要的优化还是对于资源文件的优化
-
首先我们可以和设计商量,在保证图片高保真的情况下,将图片大小尽力的去压缩。我们项目中曾有1000k+ 的大图后来压缩到 200k+ 左右,所以这样的方案还是很有用的。mac 下也有专门的软件,因为没有设计在压缩上专业,所以后来我就不再用了,有兴趣的小伙伴可以去搜一下。
-
此外,我们可以去写一个脚本,查找项目中没有被使用的图片。还可以用比较笨的方法去找命名不同但完全一致的图片。同时在日常开发中,我们可能因为UI尺寸的不同而导入同样的图片两次,其实这完全都是没有必要的,因为只导入最大的尺寸图片按照对应比例进行展示,其实展示的都是高保真图片。
-
-
最后其实是开发中的技巧,就是可能一个按钮在不一样的状态下颜色是不一样的,但是按钮的样式完全相同,此时我们可能会导入两套 UI , 其实这种情况下,我们完全可以只用一套没有颜色的UI ,然后通过代码完成图片颜色的绘制即可。
如果还有其它较好的解决方案,还希望小伙伴给我留言。此外关于前三部分的介绍,也可以查看相关的文档。文档地址
编译速度优化
随着项目一次次的功能的增加,各种框架的引入,我们的项目变大的同时,我们每次在模拟器或者真机上运行的时候,执行缓慢的问题对我们日常开发的效率造成了很大的影响,针对这样的问题,我们就要对项目进行优化,加快编译速度。这时就要了解程序的编译原理。对于编译的原理,我觉得《程序是如何跑起来的》一书,对于这一点的介绍浅显易懂,有兴趣的小伙伴可以买一本,读一下知道编译器是如何进行编译的也就能找到一些加快编译速度的方案。
-
正确的使用 .pch文件
在 Xcode 6 之前创建一个新的工程是会自带一个 .pch 文件的,但是后来苹果把这个自带的功能删除了,就是因为有很多的开发者不能正确的使用它。导致程序的编译速度变慢。所以这里会介绍介绍如何正确的进行使用。其实 .pch 文件正确使用是可以加快程序的编译速度的。
- 首先,在 .pch 文件中不要导入宏定义,因为我们都知道宏定义是去匹配的机制,如果全局匹配,无疑很耗费时间,所以在 .pch 文件中一定不要做全局的宏定义。将宏定义最好写道每一部分的头文件中。
-
其次,.pch 文件中主要进行加载的是一些比较大的文件,但是如果是我们自己写的比较大的文件,也不要加到 .pch 文件中去,因为如果一旦代码被更改,就会出现很奇怪的问题。而且加载到 .pch 文件中的文件代码在多个项目中的可复用性不好。也会对编译速度造成一定的影响。 比较建议的是可以在这个文件中导入 Foudation 、UIKit 这样常用的系统级框架
-
最后,可能会有小伙伴有这样的经历,就是像MBProgressHud 类似在全局都会经常使用到的类是不是可以放到 .pch 文件中呢,少量的几个不大的文件导入还可以,多了对于编译速度本身是不好的。
与此相关的文章可以参考 stackoverflow 相关回答
-
正确到 import 操作
在我们日常的开发中B类可能用到A类,有时候可能需要将A类在 .h 文件中声明成一个属性,这个时候可能有人就会在 .h 文件中直接 #import “AClass” 这样的做法就是不合理的,因为对于编译时而言完全不需要再这个类的全部信息编译进来,只需要知道该类被引入即可,所以此时使用 @class AClass ;更加合理,此外如果两个类互相引用对方,头文件中使用 @class 的方案不会报编译错误。另外摄像一下如果引用链如下 A -> B -> C -> D... 这样一直向下,那么这个时候,编译链条中的最后一个类发生更改,那么整个从A开始相关的类也就全部需要重新编译,那么编译时间编程也就变成了必然,所以一定注意 #import 的正确使用。
-
打包静态链接库
最近发现周围朋友的公司都在进行组件化开发,然后将每一个组件打包成 pod ,而每一个 pod 中都是一个 .a 的静态链接库。每个部门或者小组只要负责维护自己的 .a 库即可,与其它团队没有太多的影响。也不会再出现提交代码各种冲突的问题,这一点上真的很赞。但这需要很好地架构体系,因为水平原因不做展开。只是讨论 .a 文件的作用。
我们日常开发中可以将我们不会修改的三方库或者已经成熟基本不会改变的业务模块打包成 .a 的静态链接库。因为将对应文件打包生成静态链接库之后,生成的就是对应 CPU 架构下的二进制文件,在程序编译时就不会在占用编译的时间,而是在运行时,直接连接写入内存,所以可以起到优化编译速度的作用。当然打包 .a 静态库可能就会涉及到 release 和 debug 版本 ,device 和 simulator 兼容性的问题,这一点网上有很多相关的资料可以进行参考。
以上就是在编译速度上进行优化的一些个人建议。
文中出现的错误烦请您指出,我会第一时间进行修改。