列表
cocoapods 1.5更新描述
xcode9支持swift静态库,在Cocoapods 1.5.0中支持了导入swift静态库,不需要再指定 use_frameworks!
。需要注意的是当你的一个swift pod模块依赖一个OC pod模块时需要开启Modular Headers,三种方式:
1.在podfile中添加 use_modular_headers!
,这种方式将使得所有的pod模块都能使用@import导入。
platform :ios, '9.0'
use_modular_headers!
target 'staticpod' do
pod 'SwiftModule', :path => '../SwiftModule'
pod 'ObjectiveModule', :path => '../ObjectiveModule'
2.在podfile中对应的pod模块后添加 :modular_headers => true
,这种方式将使得对应的pod模块能使用@import导入。
pod 'ObjectiveModule', :path => '../ObjectiveModule', :modular_headers => true
3.在模块的podspec中添加 'DEFINES_MODULE' => 'YES'
到你的 pod_target_xcconfig
中,这种方式将指定你的podspec的模块能使用@import导入。
spec.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
PS:在cocoapod不使用 use_frameworks!
时,OC模块无法使用@import导入,use_modular_headers!
的意思是OC模块可以使用@import
#import和@import区别
#import
:
我相信每个开发者都写过这样的代码 #import <FrameworkFoo/HeaderBar.h>
,用来引用其他的头文件。熟悉C或者C++的童鞋可能会知道,在C和C++里是没有#import的,只有#include(虽然GCC现在为C和C++做了特殊处理使得import可以被编译),用来包含头文件。#include做的事情其实就是简单的复制粘贴,将目标.h文件中的内容一字不落地拷贝到当前文件中,并替换掉这句include,而#import实质上做的事情和#include是一样的,只不过OC为了避免重复引用可能带来的编译错误(这种情况在引用关系复杂的时候很可能发生,比如B和C都引用了A,D又同时引用了B和C,这样A中定义的东西就在D中被定义了两次,重复了),而加入了#import,从而保证每个头文件只会被引用一次。
@import
:
Modules相当于将框架进行了封装,然后加入在实际编译之时加入了一个用来存放已编译添加过的Modules列表。如果在编译的文件中引用到某个Modules的话,将首先在这个列表内查找,找到的话说明已经被加载过则直接使用已有的,如果没有找到,则把引用的头文件编译后加入到这个表中。这样被引用到的Modules只会被编译一次,但是在开发时又不会被意外使用到,从而同时解决了编译时间和引用泛滥两方面的问题。
测量Pre-mainTime
一个App在执行main函数前包括app delegate的系列方法如applicationWillFinishLaunching
时,会做许多系统级别的准备.而在iOS10之前,开发者很难清楚自己App为何启动加载慢.而通过在工程的scheme中添加环境变量 DYLD_PRINT_STATISTICS
,设置Value为 1
,App启动加载时就会有启动过程的日志输出. 现在(iOS 10之后)Apple对DYLD_PRINT_STATISTICS的日志输出结果进行了简化,使得更容易让开发者理解.
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%)
输出内容展示了系统调用main()函前主要进行的工作内容和时间花费,Session上也对每一阶段加载过程具体内容进行了详细的叙述,有兴趣地可观看该Session.
demo案例
1.新建工程staticpod,添加如下Podfile文件,执行 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中添加环境变量 DYLD_PRINT_STATISTICS
,设置Value为 1
。App启动加载时就会有启动过程的日志输出,可以查看pre-main时间
3.在工程中添加swift桥接文件 staticpod-Bridging-Header.h
,以支持混编
4.通过添加和删除 use_framework!
对比测试pre-main、ipa大小。PS:测试pre-main时每次请先把App从iphone中删除,避免iphone缓存影响
pre-main测试对比:
//静态库
//第一次:
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%)
//动态库
//第一次:
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大小对比:
静态库 | 动态库 |
---|---|
97.9MB | 103.5MB |
- 结论:
1.通过pre-main测试对比发现,在启动时静态库dylib loading time速度明显提升。
2.通过ipa大小对比发现,静态库比动态库ipa大小有所缩小。
注意事项
1.swift桥接文件
2.swift pod编译需要修改版本
3.在使用静态库时,无法使用 #import <Module/Module-Swift.h>
导入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之优化App启动速度"
[3]: https://blog.csdn.net/Leemin_ios/article/details/51208642 "#import、#include、@import modules区别"