隨著開發(fā)的不斷進行,我們的項目總會變得越來越大,而過大的占用用戶的內(nèi)存空間會對用戶的留存造成一定的影響,所以我們總是需要找到方案來減小我們的包大小。在我們努力的同時蘋果也在為此努力著,下文的第一部分主要介紹的就是官方文檔和個人經(jīng)驗總結(jié)出的一些關(guān)于包瘦身的方案。此外項目變大后,我們在開發(fā)時每次啟動程序的編譯時間都會變長,這對于開發(fā)者而言是效率極低的一件事,文章的第二部分主要介紹如何在編譯速度的角度去優(yōu)化程序。
項目瘦身
-
切面(Slicing)
這一功能是蘋果在 iOS 9 、watchOS 2 、tvOS 中推出的新功能,不需要我們進行任何的設(shè)置就可以完成,這個功能的主要作用在于對于不同的設(shè)備可以下發(fā)根據(jù)當前設(shè)備的CPU架構(gòu)的可執(zhí)行文件和資源文件。所以當用戶在下載APP的時候就會進行匹配,而不會向之前一樣下載針對所有設(shè)備的架構(gòu)文件了,這樣就變相的幫助我們減小了包體積。
-
Bitcode
這一功能同樣是在 iOS 9 之后推出,可以在 Xcode 7 以上版本中在 Build Setting -> Enable Bitcode ( ENABLE_BITCODE ) 先完成對應(yīng)的設(shè)置。這樣做的好處在于官方會自動的幫我們?nèi)プ鲆恍﹥?yōu)化,查看了一些國外的文章大致的猜想是蘋果在設(shè)備安裝應(yīng)用的時候,會根據(jù)設(shè)備的 CPU 架構(gòu)自動的去下發(fā)與架構(gòu)相匹配的一份二進制文件,而生成的其它 CPU 架構(gòu)的二進制文件則不被下發(fā)。這樣就可以讓我們的包體積大大減小,我們的項目可能會在 iphone4s 、 iphones 5 、iphone 6 上進行使用。如果我們用 iphone6 去下載,那么只會給我們一份 arm 64 架構(gòu)下編譯文件,而不會在下載 armv 7 和 armv 7s下的編譯文件。這樣對我們包體積的優(yōu)化還是很有必要的。
Bitcode 相關(guān)文章鏈接(自備梯子) -
資源文件下載
我們一般在開發(fā)過程中遇到的一些界面UI圖片都是放在本地的Asserts文件夾中的,所以隨著項目的擴充,我們可能會有非常多的資源文件,而此時包體積會變得非常的大。為了解決這一問題,蘋果在 iOS 9 中同樣提出了對應(yīng)的解決方案。我們可以把一些不常用的界面的 UI 存儲在蘋果的服務(wù)器上,第一次進入界面的時候,會去服務(wù)器加載相關(guān)的圖片,然后將圖片下載到本地,下次進入該頁面會從本地讀取資源文件。這樣的方案聽起來為我們解決了包體積過大的問題。
但是這樣的解決方案有如下的缺陷。
這一項功能也是在 iOS 9 之后的設(shè)備上才能夠被使用,也就是說我們的項目如果支持 iOS 8 及以下的設(shè)備還是沒有辦法完成。
這一功能下載的資源文件雖然存儲在本地,但是如果用戶的設(shè)備磁盤空間不足的時候,系統(tǒng)會優(yōu)先清空這一部分內(nèi)存,也就是說用戶可能對于這些資源需要下載多次。
因為是從蘋果服務(wù)器上拉取資源文件,所以肯定要考慮網(wǎng)絡(luò)環(huán)境的問題,如果網(wǎng)絡(luò)環(huán)境不好的情況下,這樣的方法對于用戶體驗是不友好的。
-
實戰(zhàn)方案
其實相比于我們的代碼,比較占內(nèi)存的還是資源文件,所以除了優(yōu)化本地代碼結(jié)構(gòu),更好的封裝刪除無用代碼之外,最主要的優(yōu)化還是對于資源文件的優(yōu)化
首先我們可以和設(shè)計商量,在保證圖片高保真的情況下,將圖片大小盡力的去壓縮。我們項目中曾有1000k+ 的大圖后來壓縮到 200k+ 左右,所以這樣的方案還是很有用的。mac 下也有專門的軟件,因為沒有設(shè)計在壓縮上專業(yè),所以后來我就不再用了,有興趣的小伙伴可以去搜一下。
此外,我們可以去寫一個腳本,查找項目中沒有被使用的圖片。還可以用比較笨的方法去找命名不同但完全一致的圖片。同時在日常開發(fā)中,我們可能因為UI尺寸的不同而導(dǎo)入同樣的圖片兩次,其實這完全都是沒有必要的,因為只導(dǎo)入最大的尺寸圖片按照對應(yīng)比例進行展示,其實展示的都是高保真圖片。
最后其實是開發(fā)中的技巧,就是可能一個按鈕在不一樣的狀態(tài)下顏色是不一樣的,但是按鈕的樣式完全相同,此時我們可能會導(dǎo)入兩套 UI , 其實這種情況下,我們完全可以只用一套沒有顏色的UI ,然后通過代碼完成圖片顏色的繪制即可。
如果還有其它較好的解決方案,還希望小伙伴給我留言。此外關(guān)于前三部分的介紹,也可以查看相關(guān)的文檔。文檔地址
編譯速度優(yōu)化
隨著項目一次次的功能的增加,各種框架的引入,我們的項目變大的同時,我們每次在模擬器或者真機上運行的時候,執(zhí)行緩慢的問題對我們?nèi)粘i_發(fā)的效率造成了很大的影響,針對這樣的問題,我們就要對項目進行優(yōu)化,加快編譯速度。這時就要了解程序的編譯原理。對于編譯的原理,我覺得《程序是如何跑起來的》一書,對于這一點的介紹淺顯易懂,有興趣的小伙伴可以買一本,讀一下知道編譯器是如何進行編譯的也就能找到一些加快編譯速度的方案。
-
正確的使用 .pch文件
在 Xcode 6 之前創(chuàng)建一個新的工程是會自帶一個 .pch 文件的,但是后來蘋果把這個自帶的功能刪除了,就是因為有很多的開發(fā)者不能正確的使用它。導(dǎo)致程序的編譯速度變慢。所以這里會介紹介紹如何正確的進行使用。其實 .pch 文件正確使用是可以加快程序的編譯速度的。
- 首先,在 .pch 文件中不要導(dǎo)入宏定義,因為我們都知道宏定義是去匹配的機制,如果全局匹配,無疑很耗費時間,所以在 .pch 文件中一定不要做全局的宏定義。將宏定義最好寫道每一部分的頭文件中。
其次,.pch 文件中主要進行加載的是一些比較大的文件,但是如果是我們自己寫的比較大的文件,也不要加到 .pch 文件中去,因為如果一旦代碼被更改,就會出現(xiàn)很奇怪的問題。而且加載到 .pch 文件中的文件代碼在多個項目中的可復(fù)用性不好。也會對編譯速度造成一定的影響。 比較建議的是可以在這個文件中導(dǎo)入 Foudation 、UIKit 這樣常用的系統(tǒng)級框架
最后,可能會有小伙伴有這樣的經(jīng)歷,就是像MBProgressHud 類似在全局都會經(jīng)常使用到的類是不是可以放到 .pch 文件中呢,少量的幾個不大的文件導(dǎo)入還可以,多了對于編譯速度本身是不好的。
與此相關(guān)的文章可以參考 stackoverflow 相關(guān)回答
-
正確到 import 操作
在我們?nèi)粘5拈_發(fā)中B類可能用到A類,有時候可能需要將A類在 .h 文件中聲明成一個屬性,這個時候可能有人就會在 .h 文件中直接 #import “AClass” 這樣的做法就是不合理的,因為對于編譯時而言完全不需要再這個類的全部信息編譯進來,只需要知道該類被引入即可,所以此時使用 @class AClass ;更加合理,此外如果兩個類互相引用對方,頭文件中使用 @class 的方案不會報編譯錯誤。另外攝像一下如果引用鏈如下 A -> B -> C -> D... 這樣一直向下,那么這個時候,編譯鏈條中的最后一個類發(fā)生更改,那么整個從A開始相關(guān)的類也就全部需要重新編譯,那么編譯時間編程也就變成了必然,所以一定注意 #import 的正確使用。
-
打包靜態(tài)鏈接庫
最近發(fā)現(xiàn)周圍朋友的公司都在進行組件化開發(fā),然后將每一個組件打包成 pod ,而每一個 pod 中都是一個 .a 的靜態(tài)鏈接庫。每個部門或者小組只要負責維護自己的 .a 庫即可,與其它團隊沒有太多的影響。也不會再出現(xiàn)提交代碼各種沖突的問題,這一點上真的很贊。但這需要很好地架構(gòu)體系,因為水平原因不做展開。只是討論 .a 文件的作用。
我們?nèi)粘i_發(fā)中可以將我們不會修改的三方庫或者已經(jīng)成熟基本不會改變的業(yè)務(wù)模塊打包成 .a 的靜態(tài)鏈接庫。因為將對應(yīng)文件打包生成靜態(tài)鏈接庫之后,生成的就是對應(yīng) CPU 架構(gòu)下的二進制文件,在程序編譯時就不會在占用編譯的時間,而是在運行時,直接連接寫入內(nèi)存,所以可以起到優(yōu)化編譯速度的作用。當然打包 .a 靜態(tài)庫可能就會涉及到 release 和 debug 版本 ,device 和 simulator 兼容性的問題,這一點網(wǎng)上有很多相關(guān)的資料可以進行參考。
以上就是在編譯速度上進行優(yōu)化的一些個人建議。
文中出現(xiàn)的錯誤煩請您指出,我會第一時間進行修改。