一、介紹
1、背景
考慮到上架App的安全性和后期代碼管理的一些內容,以及現有馬甲和超級App的一些業務上,越來越多的涉及到大模塊的內容搬移和共享,所以權衡各種方式之后,考慮使用靜態庫的方式來把獨立業務部分用靜態庫的方式加載和共享。
2、靜態庫介紹
- 什么是庫?
共享代碼便是庫,實現代碼的復用,一般分為靜態庫和動態庫。
- 靜態庫和動態庫的區別?
靜態庫:鏈接時完整的拷貝到可執行文件,多次使用多次拷貝,造成冗余,使包變的更大。
動態庫:鏈接時不復制,程序運行時由系統加在到內存中,供系統調用,系統加在一次,多次使用,共用節省內存。
- iOS/Mac 中的靜態庫?
后綴為: .a和.framework 文件
- iOS/Mac 中的動態庫?
后綴為: .dylib和.framework 文件
- iOS/Mac Framework 為什么即是動態又是靜態?
系統的架構是動態的,我們自己創建的是靜態的。
- .a和.framework的區別是什么?
.a是單純的二進制文件,.framework是二進制問價+資源文件。
其中.a不能直接使用,需要.h文件配合,而.framework則可以直接使用
.framework = .a + .h + sorrceFile(資源文件)
- 為什么要使用靜態庫?
共享代碼,方便使用。
實現iOS 程序的模塊化,固定的業務模塊話,減少開發的重復勞動。
和別人分享代碼,但又不想讓別人知道代碼的具體實現。
開發第三方SDK 的需要。
有時候集成其他項目的時候 也可以使用。
3、注意點
- AppDelegate
AppDelegate不能打包進靜態庫,所以AppDelegate.m文件在編譯的文件列表中要撤選,在AppDelegate中做的一些操作要全部封裝成接口暴露出去
- 第三方庫
項目中的第三方庫優先使用CocoaPods管理,可以不用打包進自己的靜態庫。如果我們打包整個工程的時候沒有把用到的第三方框架一起打包,那么提供靜態庫的時候,要說明依賴哪些第三方的庫。
- 資源文件
默認情況下,靜態庫只會打包代碼文件,像圖片、xib、storyboard、plist文件等都不會被打包,就需要創建一個bundle文件夾,把所有的圖片、plist文件、Images.xcassets、xib、storyboard都打包進去,而且項目中用到圖片的時候,只能通過bundle/xxx.png文件名的方式來設置。
二、封裝步驟
1、新建工程
- 選擇File>New>Project>iOS>Cocoa Touch Framework
2、導入文件
- 先刪除系統自動生成的工程同名的.h文件,創建相同名稱繼承自NSObject的類,用于對外暴露接口的類,到時候只需把創建的.h暴露出去即可。
- 拉取需要制作靜態庫的所有文件資源到新工程目錄下。
3、導入第三方庫
- 使用CocoaPods管理的第三方庫,在此工程下,同樣配置需要支持的第三方庫的Podfile后執行pod install,并用.xcworkspace文件重新打開工程。
- 非CocoaPods管理的第三方庫,連同資源文件一起拉進工程目錄下,并部署對應的依賴和系統庫,必要時,把第三方的.h文件暴露成Public。
4、創建bundle文件
- 創建一個bundle文件,命名為:Resources,把項目中用到的圖片或者其他非代碼資源都拖拽進去。
- 讀取的時候需要帶上讀取路徑,示例:
[_searchButton setImage:[UIImage imageNamed:@"Resources.bundle/search.png"] forState:UIControlStateNormal];
5、修改pch文件路徑
- 若原來的文件中包含pch文件用來做全局引用,需要再此工程中修改pch文件路徑。
6、工程配置
- 修改支持設備、版本和架構
注意:.Build Setting搜索linking設置Dead Code Stripping為NO是編譯選項優化,可以使包瘦身,可以根據具體要求選擇是否修改。
備注說明
不同的模擬器和真機所支持的CPU架構是不一樣的,如果庫文件不支持某種CPU架構,那么就無法在對應的設備上編譯。
模擬器環境下支持的CPU架構:
4s — 5:支持i386架構,CPU處理器是32位的
5s — 6Plus:支持x86_64架構,CPU處理器是64位的
真機環境下支持的CPU架構:
3gs — 4s:支持armv7架構,CPU處理器是32位的
5 — 5c:支持armv7s架構,CPU處理器是32位的
5s — 6Plus及以上:支持arm64架構,CPU處理器是64位的
Architectures屬性是系統根據你的Xcode版本自動默認配置的,如果你當前的Xcode版本比較舊,默認的真機架構有可能只是:armv7,而我目前的版本是Xcode9.4,Architectures的默認設置只有兩種架構:armv7和arm64。
Valid Architectures選項里面卻有三種架構,包括arm64,armv7,armv7s,在打包成靜態庫的時候,Xcode會拿到這兩個選項里面的參數進行比較,只保留在兩個選項里都同時存在的架構。
7、頭文件配置
根據需要開放的.h拖動Project的文件到Public列,需要隱藏的拖動到Private。
注意:因為 Framwork 工程是沒有自動導入系統的 UIKit.framwork,我們Framwork里面是用到了UI控件的,所以需要手動導入系統UI庫。否則封裝完畢,調用該庫的時候,里面的UI控件是不可見的。
8、工程編譯
- 編譯之前需要進行Edit Scheme,把Debug修改成Release。
- 選擇真機(或者Generic iOS Device)和模擬器都編譯一次,編譯通過后,選擇Products文件夾,對應生成的framework文件Show in Finder,會發現有對應生成的真機和模擬器的framework。
9、合并Framework
- 先檢查一下對應的framework架構信息是否正確,打開終端使用命令行:
lipo -info 空格 framework地址
- 合并真機和模擬器的framework,使用命令行處理:
sudo lipo -create 空格 (此處請填寫真機testNewFramework文件路徑) 空格 (此處填寫模擬器testNewFramework文件路徑) 空格 -output 空格 自定義合成文件存儲路徑(合成文件的名字testNewFramework)
- 最后查看合并后的framework架構信息是否包含真機和模擬器的所有的架構信息。
備注說明
架構信息:首先了解一下什么是ARM,ARM是微處理器,而armv6, armv7, armv7s是ARM CPU的不同指令集。
armv6設備:iPhone, iPhone2, iPhone 3G,第一代、第二代iPod Touch
armv7設備:iPhone 3GS,iPhone 4,iPhone 4S,iPad ,iPad 2,iPod Touch 3G,iPod Touch 4
armv7s設備:iPhone 5,iPad4
arm64設備:iPhone 5S,iPad Air,iphone6,iphone6plus,iPhone6s,iPhone6s Plus及以上版本等。
三、使用Framework
1、拖入主程序
- 直接將生成的framework拖入要使用的工程中去,使用文件復制類型加載。
- 引入framework,否則會娶不到framework的圖片等資源。
2、使用功能
- 對應暴露的.h文件,可以直接使用#improt <framework名稱/指定.h>來引用頭文件。
- 對于framework的其他資源文件,可以使用讀取bundle資源包的路徑來獲取,示例:
[_searchButton setImage:[UIImage imageNamed:@"Resources.bundle/search.png"] forState:UIControlStateNormal];
至此,教程完畢。