pod使用靜態(tài)庫(kù),提升App啟動(dòng)速度,降低包大小

列表

cocoapods 1.5更新描述

xcode9支持swift靜態(tài)庫(kù),在Cocoapods 1.5.0中支持了導(dǎo)入swift靜態(tài)庫(kù),不需要再指定 use_frameworks! 。需要注意的是當(dāng)你的一個(gè)swift pod模塊依賴一個(gè)OC pod模塊時(shí)需要開啟Modular Headers,三種方式:
1.在podfile中添加 use_modular_headers! ,這種方式將使得所有的pod模塊都能使用@import導(dǎo)入。

platform :ios, '9.0'
use_modular_headers!

target 'staticpod' do
 pod 'SwiftModule', :path => '../SwiftModule'
 pod 'ObjectiveModule', :path => '../ObjectiveModule'

2.在podfile中對(duì)應(yīng)的pod模塊后添加 :modular_headers => true ,這種方式將使得對(duì)應(yīng)的pod模塊能使用@import導(dǎo)入。

pod 'ObjectiveModule', :path => '../ObjectiveModule', :modular_headers => true

3.在模塊的podspec中添加 'DEFINES_MODULE' => 'YES' 到你的 pod_target_xcconfig 中,這種方式將指定你的podspec的模塊能使用@import導(dǎo)入。

spec.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }

PS:在cocoapod不使用 use_frameworks! 時(shí),OC模塊無(wú)法使用@import導(dǎo)入,use_modular_headers! 的意思是OC模塊可以使用@import

#import和@import區(qū)別

#import :

? 我相信每個(gè)開發(fā)者都寫過(guò)這樣的代碼 #import <FrameworkFoo/HeaderBar.h> ,用來(lái)引用其他的頭文件。熟悉C或者C++的童鞋可能會(huì)知道,在C和C++里是沒有#import的,只有#include(雖然GCC現(xiàn)在為C和C++做了特殊處理使得import可以被編譯),用來(lái)包含頭文件。#include做的事情其實(shí)就是簡(jiǎn)單的復(fù)制粘貼,將目標(biāo).h文件中的內(nèi)容一字不落地拷貝到當(dāng)前文件中,并替換掉這句include,而#import實(shí)質(zhì)上做的事情和#include是一樣的,只不過(guò)OC為了避免重復(fù)引用可能帶來(lái)的編譯錯(cuò)誤(這種情況在引用關(guān)系復(fù)雜的時(shí)候很可能發(fā)生,比如B和C都引用了A,D又同時(shí)引用了B和C,這樣A中定義的東西就在D中被定義了兩次,重復(fù)了),而加入了#import,從而保證每個(gè)頭文件只會(huì)被引用一次。

@import :

? Modules相當(dāng)于將框架進(jìn)行了封裝,然后加入在實(shí)際編譯之時(shí)加入了一個(gè)用來(lái)存放已編譯添加過(guò)的Modules列表。如果在編譯的文件中引用到某個(gè)Modules的話,將首先在這個(gè)列表內(nèi)查找,找到的話說(shuō)明已經(jīng)被加載過(guò)則直接使用已有的,如果沒有找到,則把引用的頭文件編譯后加入到這個(gè)表中。這樣被引用到的Modules只會(huì)被編譯一次,但是在開發(fā)時(shí)又不會(huì)被意外使用到,從而同時(shí)解決了編譯時(shí)間和引用泛濫兩方面的問(wèn)題。

測(cè)量Pre-mainTime

一個(gè)App在執(zhí)行main函數(shù)前包括app delegate的系列方法如applicationWillFinishLaunching時(shí),會(huì)做許多系統(tǒng)級(jí)別的準(zhǔn)備.而在iOS10之前,開發(fā)者很難清楚自己App為何啟動(dòng)加載慢.而通過(guò)在工程的scheme中添加環(huán)境變量 DYLD_PRINT_STATISTICS ,設(shè)置Value為 1 ,App啟動(dòng)加載時(shí)就會(huì)有啟動(dòng)過(guò)程的日志輸出. 現(xiàn)在(iOS 10之后)Apple對(duì)DYLD_PRINT_STATISTICS的日志輸出結(jié)果進(jìn)行了簡(jiǎn)化,使得更容易讓開發(fā)者理解.

Total pre-main time: 1.5 seconds (100.0%)
     dylib loading time: 927.09 milliseconds (58.8%)
    rebase/binding time:  42.65 milliseconds (2.7%)
        ObjC setup time: 365.58 milliseconds (23.2%)
       initializer time: 239.06 milliseconds (15.1%)
       slowest intializers :
         libSystem.B.dylib :  16.71 milliseconds (1.0%)
libMainThreadChecker.dylib : 111.62 milliseconds (7.0%)
                   ModelIO :  39.38 milliseconds (2.5%)
                 staticpod :  76.22 milliseconds (4.8%)

輸出內(nèi)容展示了系統(tǒng)調(diào)用main()函前主要進(jìn)行的工作內(nèi)容和時(shí)間花費(fèi),Session上也對(duì)每一階段加載過(guò)程具體內(nèi)容進(jìn)行了詳細(xì)的敘述,有興趣地可觀看該Session.

demo案例

1.新建工程staticpod,添加如下Podfile文件,執(zhí)行 pod install

platform :ios, '9.0'
#use_frameworks!
use_modular_headers!

target 'staticpod' do
    #OC模塊
    pod 'Qiniu'
    pod 'HappyDNS'
    pod 'Masonry'
    pod 'MJRefresh'
    pod 'SDWebImage'
    pod 'MJExtension'
    pod 'pop'
    pod 'FSCalendar'
    pod 'FLAnimatedImage'
    pod 'AFNetworking'

    #swift模塊
    pod 'Alamofire'
    pod 'SwiftyJSON'
    pod 'DZNEmptyDataSet'
    pod 'lottie-ios'
    pod 'FileKit'
    pod 'SwiftyUserDefaults'
    pod 'Hero'
end

post_install do |installer|
    installer.pods_project.targets.each do |target|
            target.build_configurations.each do |config|
                config.build_settings['SWIFT_VERSION'] = '4.1'
        end
    end
end

2.在工程的scheme中添加環(huán)境變量 DYLD_PRINT_STATISTICS ,設(shè)置Value為 1 。App啟動(dòng)加載時(shí)就會(huì)有啟動(dòng)過(guò)程的日志輸出,可以查看pre-main時(shí)間

3.在工程中添加swift橋接文件 staticpod-Bridging-Header.h ,以支持混編

4.通過(guò)添加和刪除 use_framework! 對(duì)比測(cè)試pre-main、ipa大小。PS:測(cè)試pre-main時(shí)每次請(qǐng)先把App從iphone中刪除,避免iphone緩存影響

pre-main測(cè)試對(duì)比:

//靜態(tài)庫(kù)
//第一次:
Total pre-main time: 1.5 seconds (100.0%)
     dylib loading time: 927.09 milliseconds (58.8%)
    rebase/binding time:  42.65 milliseconds (2.7%)
        ObjC setup time: 365.58 milliseconds (23.2%)
       initializer time: 239.06 milliseconds (15.1%)
       slowest intializers :
         libSystem.B.dylib :  16.71 milliseconds (1.0%)
libMainThreadChecker.dylib : 111.62 milliseconds (7.0%)
                   ModelIO :  39.38 milliseconds (2.5%)
                 staticpod :  76.22 milliseconds (4.8%)

//第二次:
Total pre-main time: 1.2 seconds (100.0%)
     dylib loading time: 899.49 milliseconds (72.0%)
    rebase/binding time:  25.12 milliseconds (2.0%)
        ObjC setup time: 222.38 milliseconds (17.8%)
       initializer time: 100.92 milliseconds (8.0%)
       slowest intializers :
         libSystem.B.dylib :  10.80 milliseconds (0.8%)
libMainThreadChecker.dylib :  27.79 milliseconds (2.2%)
                 staticpod :  38.54 milliseconds (3.0%)

//第三次:
Total pre-main time: 1.4 seconds (100.0%)
     dylib loading time: 964.68 milliseconds (67.1%)
    rebase/binding time:  26.76 milliseconds (1.8%)
        ObjC setup time: 300.70 milliseconds (20.9%)
       initializer time: 143.86 milliseconds (10.0%)
       slowest intializers :
         libSystem.B.dylib :  11.79 milliseconds (0.8%)
libMainThreadChecker.dylib :  55.83 milliseconds (3.8%)
                 staticpod :  49.46 milliseconds (3.4%)

//動(dòng)態(tài)庫(kù)
//第一次:
Total pre-main time: 1.9 seconds (100.0%)
     dylib loading time: 1.5 seconds (81.9%)
    rebase/binding time:  41.20 milliseconds (2.1%)
        ObjC setup time: 184.62 milliseconds (9.4%)
       initializer time: 126.52 milliseconds (6.4%)
       slowest intializers :
         libSystem.B.dylib :  11.67 milliseconds (0.5%)
libMainThreadChecker.dylib :  75.59 milliseconds (3.8%)

//第二次:
Total pre-main time: 2.8 seconds (100.0%)
     dylib loading time: 2.3 seconds (82.7%)
    rebase/binding time:  29.70 milliseconds (1.0%)
        ObjC setup time: 302.37 milliseconds (10.7%)
       initializer time: 153.19 milliseconds (5.4%)
       slowest intializers :
         libSystem.B.dylib :  18.91 milliseconds (0.6%)
libMainThreadChecker.dylib :  58.05 milliseconds (2.0%)

//第三次:
Total pre-main time: 1.7 seconds (100.0%)
     dylib loading time: 1.6 seconds (91.7%)
    rebase/binding time:  41.66 milliseconds (2.3%)
        ObjC setup time:  34.16 milliseconds (1.9%)
       initializer time:  69.59 milliseconds (3.9%)
       slowest intializers :
         libSystem.B.dylib :  13.77 milliseconds (0.7%)

ipa大小對(duì)比:

靜態(tài)庫(kù) 動(dòng)態(tài)庫(kù)
97.9MB 103.5MB
  1. 結(jié)論:
    1.通過(guò)pre-main測(cè)試對(duì)比發(fā)現(xiàn),在啟動(dòng)時(shí)靜態(tài)庫(kù)dylib loading time速度明顯提升。
    2.通過(guò)ipa大小對(duì)比發(fā)現(xiàn),靜態(tài)庫(kù)比動(dòng)態(tài)庫(kù)ipa大小有所縮小。

注意事項(xiàng)

1.swift橋接文件

2.swift pod編譯需要修改版本

3.在使用靜態(tài)庫(kù)時(shí),無(wú)法使用 #import <Module/Module-Swift.h> 導(dǎo)入swift文件,必須使用@import Module

參考:
[1]: http://blog.cocoapods.org/CocoaPods-1.5.0/ "Cocoapods 1.5.0更新文檔"
[2]: https://blog.csdn.net/khlljm/article/details/52386594 "WWDC之優(yōu)化App啟動(dòng)速度"
[3]: https://blog.csdn.net/Leemin_ios/article/details/51208642 "#import、#include、@import modules區(qū)別"

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容