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

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

1、將需要打包成 Framework 的模塊導入到項目中,設置最低支持的 iOS 版本,編譯項目保證不報錯。
111.png

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

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

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

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

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

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

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

打包framework注意事項:

如果有storyboard、xib,需要在對應的視圖控制器中添加以下代碼:

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

        // 如果是xib
        self = [super initWithNibName:@"當前控制器的名稱" 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");

定義一個資源管理宏:

#define Debug_Env 0    // 開發(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

這個資源管理宏也可以寫得更方便些:

#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

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

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

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

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

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

Framework.png

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

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

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

真機編譯.png

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

Scheme.png

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

合成.png

注意,一般是 debug 真機跟 debug 模擬器合成,release 真機跟 release模擬器合成,debug 和 release 不要混合,當然,兩個模擬器或者兩個真機合成會失敗。最終會分別有一個 debug 下和 release 下的 framework。

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

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

333.png

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

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

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

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

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

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