iOS打包framework靜態(tài)庫(kù)

制作 .framework 靜態(tài)庫(kù)的步驟:

1、將需要打包成 Framework 的模塊導(dǎo)入到項(xiàng)目中,設(shè)置最低支持的 iOS 版本,編譯項(xiàng)目保證不報(bào)錯(cuò)。
111.png

2、創(chuàng)建一個(gè)新的靜態(tài)庫(kù)的 Target。
221.png
222.png
223.png

3、在 TARGETS 中選中新建的靜態(tài)庫(kù) Target,Build Phases 里配置文件。
224.png
225.png

4、把 Podfile 中所有庫(kù)注釋掉然后 pod install,然后刪除 Podfile 文件同級(jí)別目錄下其它所有 pods 相關(guān)的文件。

5、使用 .xcodeproj(注意不是workspace)打開(kāi)項(xiàng)目,選中工程的 Target,在 Build Phases 下刪除 Check Pods Manifest.lock 和 Copy Pods Resources。
226.png

6、打開(kāi) Podfile文件中前面注釋的庫(kù),在下面為靜態(tài)庫(kù) Target 添加第三方庫(kù),然后 pod install。
227.png

7、選擇靜態(tài)庫(kù) Target,在 Build Settings 中搜索 mach,將 Mach-O Type 改為 Static Library;搜索 Other C Flags,添加命令“-fembed-bitcode”,同樣的設(shè)置在PROJECT中,如果不進(jìn)行以上操作,別人在集成你的framework時(shí)可以編譯,也可以真機(jī)測(cè)試。唯獨(dú)在打包時(shí)會(huì)發(fā)出警告并打包失敗,警告為framework不支持bitcode。
228.png
231.png
232.png

8、最后編譯即可生成靜態(tài)庫(kù)。

打包framework注意事項(xiàng):

如果有storyboard、xib,需要在對(duì)應(yīng)的視圖控制器中添加以下代碼:

- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"你的靜態(tài)庫(kù)名稱(chēng)" withExtension:@"framework"]];
    if (bundle) {
        // 如果是storyboard
        UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"你的storyboard名稱(chēng)(例如Main)" bundle:bundle];
        self = [storyboard instantiateViewControllerWithIdentifier:@"你在storyboard中設(shè)置的此視圖控制器的id"];
        return self;

        // 如果是xib
        self = [super initWithNibName:@"當(dāng)前控制器的名稱(chēng)" bundle:bundle];
        return self;
    }
    return [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
}

如果需要加載圖片:

NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"Frameworks" withExtension:@"framework"]];
NSString *bundlePath = [bundle resourcePath];
UIImage *img = [UIImage imageWithContentsOfFile:[bundlePath stringByAppendingString:@"/aaa.png"]];

使用圖片宏:

#define Bundle_With_Framework(name) [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:name withExtension:@"framework"]]
#define Framework_Bundle Bundle_With_Framework(@"Frameworks")
#define ImageNamed(name) Framework_Bundle ? [UIImage imageWithContentsOfFile:[[Framework_Bundle resourcePath] stringByAppendingString:[NSString stringWithFormat:@"/%@", name]]] : [UIImage imageNamed:name]
self.img.image = ImageNamed(@"gg.jpg");

定義一個(gè)資源管理宏:

#define Debug_Env 0    // 開(kāi)發(fā)環(huán)境
#define Release_Env 1  // 打包環(huán)境

#if Release_Env

#define MR_Bundle [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"StaticLibrary" withExtension:@"framework"]]
#define MR_BundleWith(res) [[MR_Bundle resourcePath] stringByAppendingPathComponent:res]
#else

#define MR_Bundle [NSBundle mainBundle]
#define MR_BundleWith(res) res
#endif

這個(gè)資源管理宏也可以寫(xiě)得更方便些:

#define Framework_Bundle [[NSBundle mainBundle] URLForResource:@"MRFramework" withExtension:@"framework"]

#define MR_Bundle Framework_Bundle ? [NSBundle bundleWithURL:Framework_Bundle] : [NSBundle mainBundle]
#define MR_BundleWith(res) Framework_Bundle ? [[[NSBundle bundleWithURL:Framework_Bundle] resourcePath] stringByAppendingPathComponent:res] : res

加載圖片時(shí):[UIImage imageNamed:MR_BundleWith(@"picture.png")]
加載 storyboard 時(shí):[UIStoryboard storyboardWithName:@"Storyboard" bundle:MR_Bundle];

如果靜態(tài)庫(kù)中有 ClassA.h、ClassB.h、ClassC.h 三個(gè)頭文件,如果只對(duì)外暴露 ClassA.h,那么 ClassA.h 中就不能引用 ClassB 和 ClassC,只能在 ClassA.m 中引用。

合并最終的靜態(tài)庫(kù):

模擬器 iPhone5s 以下是 i386 架構(gòu),iPhone5s 及以上是 x86_64 架構(gòu)。
真機(jī)iPhone5s 以下是 armv7 架構(gòu),iPhone5s 及以上是 arm64 架構(gòu)。

終端 cd 到生成的 framework 文件夾中,使用命令 lipo -info framework名,可以看到打出的庫(kù)是 x86_64 架構(gòu)的。

Framework.png

如果想同時(shí)支持 i386 和 x86_64,設(shè)置:
Build Settings —> Architectures —> Build Active Architecture Only —> NO。

架構(gòu)設(shè)置.png
架構(gòu)查看.png

模擬器選擇真機(jī),編譯之后會(huì)生成真機(jī)的 framework ,架構(gòu)是 armv7 和 arm64。

真機(jī)編譯.png

以上真機(jī)和模擬器的 framework都是 DEBUG 模式下的,打開(kāi) Scheme,選為 Release 模式再編譯兩次(真機(jī)和模擬器):

Scheme.png

使用命令:lipo -create path1 path2 -output 合成文件名
可以將真機(jī)和模擬器兩個(gè) framework 合成為一個(gè)。其中 path1 和 path2 都是下圖中紅圈中的文件:

合成.png

注意,一般是 debug 真機(jī)跟 debug 模擬器合成,release 真機(jī)跟 release模擬器合成,debug 和 release 不要混合,當(dāng)然,兩個(gè)模擬器或者兩個(gè)真機(jī)合成會(huì)失敗。最終會(huì)分別有一個(gè) debug 下和 release 下的 framework。

framework靜態(tài)庫(kù)使用步驟:

1、將靜態(tài)庫(kù)拖入工程,然后在 Build Phases —> Copy Bundle Resources 中添加該靜態(tài)庫(kù)。

333.png

2、如果靜態(tài)庫(kù)中有分類(lèi)(Category),則需要在 Build Settings —> Other Linker Flags 中添加 -ObjC 或 -all_load,如果靜態(tài)庫(kù)調(diào)用 pods 中的第三方庫(kù)崩潰,則添加$(inherited)。(-ObjC鏈接所有OC文件,-all_load是鏈接所有文件,-force_load文件路徑是鏈接指定路徑文件,多個(gè)靜態(tài)庫(kù)文件沖突時(shí)使用-force_load,$(inherited)的含義
334.png

3、如果靜態(tài)庫(kù)中引用了AFNetworking等第三方庫(kù),需要工程也導(dǎo)入這這些庫(kù),否則會(huì)報(bào)頭文件找不到的錯(cuò)誤。
4、如果使用者導(dǎo)入靜態(tài)庫(kù)頭文件報(bào)警告 missing submodule ,說(shuō)明靜態(tài)庫(kù)中有頭文件找不到。如果打包工程名和某個(gè)類(lèi)的名稱(chēng)相同,也會(huì)報(bào)這個(gè)警告,只需要把這個(gè)類(lèi)名改成其它名稱(chēng)即可。

參考《iOS靜態(tài)庫(kù)》、《打包Framework并引用CocoaPods管理》。
一般打包了靜態(tài)庫(kù)之后,還需要制作說(shuō)明文檔,文檔制作可參考《安裝和使用AppleDoc》《使用AppleDoc自動(dòng)生成項(xiàng)目文檔》。

最后編輯于
?著作權(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)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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