一做粤、創(chuàng)建
1浇借、新建項目
打開Xcode,菜單:File -- New -- Project...怕品,選擇iOS -- Framework -- Next妇垢,取名比如MySDK,保存。
2闯估、修改Schemes
菜單 Project -- Scheme -- Edit Scheme...灼舍,Debug 改成 Release
3、修改版本號和最低適配的iOS系統(tǒng)版本
4涨薪、配置 Build Settings
- Base SDK:iOS(基礎(chǔ)系統(tǒng))
- Build Active Architecture Only:NO(編譯所有版本的Architecture)
- Dead Code Stripping:NO(不去除被定義但未被調(diào)用的代碼骑素,瘦身可用)
- Mach-O Type:Static Library 或 Relocatable Object File(靜態(tài)庫類型)
- Link With Standard Libraries:NO(編譯器在鏈接時不自動使用標準庫的鏈接器,需配置 Other Linker Flags 來指定鏈接器)
- Other Linker Flags:-ObjC(如果framework中包含類目刚夺,需要添加)
- Enable Bitcode:NO(根據(jù)具體項目需求)
- Debug Information Format:DWARF(不光能提高編譯效率献丑,友盟也能分析到靜態(tài)庫里奔潰的地方)
5、擴展
5.1 Mach-O Type的五種類型
- Executable:可執(zhí)行二進制文件侠姑,應用的主要二進制
- Dynamic Library:動態(tài)鏈接庫(又稱DSO或DLL)
- Bundle:非獨立二進制文件创橄,顯式加載;不能被鏈接的Dylib结借,只能在運行時使用dlopen( )加載筐摘,可當做macOS的插件
- Static Library:靜態(tài)鏈接庫
- Relocatable Object File:可重定位的目標文件,中間結(jié)果(包體積最写稀)
5.2 鏈接庫
鏈接庫可以分為靜態(tài)庫和動態(tài)庫咖熟,靜態(tài)庫有.a和.framework類型的的文件,動態(tài)庫有.dylib和.framework柳畔。系統(tǒng)的.framework是動態(tài)庫馍管,我們自己建立的.framework是靜態(tài)庫。
靜態(tài)庫:鏈接時完整地拷貝至可執(zhí)行文件中薪韩,被多次使用就有多份冗余拷貝确沸。
動態(tài)庫:鏈接時不復制,程序運行時由系統(tǒng)動態(tài)加載到內(nèi)存俘陷,供程序調(diào)用罗捎,系統(tǒng)只加載一次,多個程序共用拉盾,節(jié)省內(nèi)存桨菜。
二、添加代碼
1捉偏、個人代碼
創(chuàng)建兩個類 MyTools 和 MyBase
添加一個方法倒得,用于測試
// MyTools.h
// MySDK
//
// Created by 于建祥 on 2020/7/27.
// Copyright ? 2020 com.jzsec. All rights reserved.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MyTools : NSObject
+(void)firstMethod;
@end
NS_ASSUME_NONNULL_END
// MyTools.m
// MySDK
//
// Created by z on 2020/7/27.
// Copyright ? 2020 com.jzsec. All rights reserved.
#import "MyTools.h"
@implementation MyTools
+(void)firstMethod
{
NSLog(@"MyTools First Method");
}
@end
2、導入第三方庫
在開發(fā)過程中或多或少都會用到一些第三方庫夭禽,其中又分為源碼和靜態(tài)庫霞掺,純源碼的第三方還還說,直接拖進工程讹躯。比如我們拖進MJRfresh
2.1菩彬、第三方庫沖突
如果在外界的工程里也用到了MJRfresh怎么辦缠劝,framework里也有就編譯報錯。此時如果只是引用并沒有修改第三方挤巡,而且外界也用到了這個第三方剩彬,那么在把這個第三方拖進工程的時候就不要選 Add to targets ?崧蟆?蟊啊!
有時候我們?yōu)榱诵枨髸薷牡谌皆创a沃饶,但是又不能被外界的第三方替換了母廷,此時可以勾選 Add to targets 把第三方打進framework,前提是要把第三方的類和文件重命名:簟琴昆!
2.2、第三方庫為靜態(tài)庫
有的第三方是靜態(tài)庫的形式馆揉,無法修改源碼业舍,比如微信,也可直接拖進工程升酣,根據(jù)需求勾選 Add to targets
但如果第三方庫也是framework的形式怎么辦呢舷暮?可以把它拆包,以我這個framework為例:
framework包的內(nèi)部結(jié)構(gòu)如上噩茄,我們需要把Headers整個文件夾和framework同名的靜態(tài)文件復制出來下面,并把這個靜態(tài)庫文件加個后綴.a,如下把這個文件夾導入工程即可绩聘。
3沥割、設(shè)置公開頭文件
在當前target的 Build Phases 的Headers里有三個分組,默認創(chuàng)建的文件都在 Project 分組里凿菩,即非公開的机杜,如果要給外面使用,就把頭文件拖到 Public 分組里
創(chuàng)建完工程衅谷,會自動生成一個和framework同名的頭文件MySDK.h椒拗,此文件里是要import我們需要暴露的所有類的頭文件。比如在里面:
#import <Foundation/Foundation.h>
//! Project version number for MySDK.
FOUNDATION_EXPORT double MySDKVersionNumber;
//! Project version string for MySDK.
FOUNDATION_EXPORT const unsigned char MySDKVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <MySDK/PublicHeader.h>
#import "MyTools.h"
此處不一定非要把Public分組里的文件都導入会喝,可以導入一些常用的陡叠,否則用戶把這個頭文件已導入就會導入特別多的文件,防止編譯出錯或編譯過慢肢执。
三枉阵、編譯
編譯前還要在 General 的 frameworks and Libraries 導入系統(tǒng)的依賴庫(如果有的話)
1、完成前面的配置和開發(fā)工作后预茄,運行一下項目兴溜,發(fā)現(xiàn)報錯了:
這是因為 compatibility_version 是動態(tài)庫才會用到的侦厚,需要去 Build Settings 里刪掉對應的版本號:
這兩個都要刪除,重新運行拙徽,編譯通過刨沦。
2、還有可能有一種編譯報錯:
error: ***.framework' in the Link Binary With Libraries build phase is using platform filters which is not supported in the legacy build system.
有兩種解決辦法:
- project Setting中 修改為“New Build System”
- Build Phases 中 link binary with Libaries 中對應報錯的framework 的Platforms 修改為macOS + iOS
四膘怕、合成
開發(fā)完成之后想诅,要給別人使用此framework,就要打出包岛心,分別選擇device和模擬器来破,運行
對Products的framework右鍵 Show in Finder,找到文件所在位置:
如下忘古,真機和模擬器都對應的生成了一個framework:
要把這兩個framework合成一個徘禁,才能給別人使用,否則就只能在真機或模擬器環(huán)境下使用髓堪。
合并其實就是合并的framework包里的靜態(tài)庫文件:
查看當前靜態(tài)庫支持的設(shè)備:
lipo -info 靜態(tài)庫文件路徑
比如:
~ $ lipo -info /Users/z/Desktop/Release-iphoneos/MySDK.framework/MySDK
Architectures in the fat file: /Users/z/Desktop/Release-iphoneos/MySDK.framework/MySDK are: armv7 arm64
~ $ lipo -info /Users/z/Desktop/Release-iphonesimulator/MySDK.framework/MySDK
Architectures in the fat file: /Users/z/Desktop/Release-iphonesimulator/MySDK.framework/MySDK are: i386 x86_64
- armv7 arm64 :真機
- i386 x86_64 :模擬器
合并指令:
lipo -create 真機路徑 模擬器路徑 -output 輸出文件路徑
比如:
lipo -create /Users/z/Desktop/Release-iphoneos/MySDK.framework/MySDK /Users/z/Desktop/Release-iphonesimulator/MySDK.framework/MySDK -output /Users/z/Desktop/result/MySDK
再用lipo -info命令查看輸出的合并后新的文件:
~ $ lipo -info /Users/z/Desktop/result/MySDK
Architectures in the fat file: /Users/z/Desktop/result/MySDK are: armv7 i386 x86_64 arm64
這時候得到的是:armv7 i386 x86_64 arm64
我們拷貝一份真機下的包送朱,然后將上步中得到的合并后的文件替換進去,最終就是兼容版本包干旁。
五驶沼、使用
接下來我們新建一個工程來測試一下新打出的framework
導入剛打出的 MySDK.framework,并添加系統(tǒng)依賴庫和第三方依賴庫(第二步導入第三方未勾選 Add to targets的)疤孕,在ViewController.m導入頭文件商乎,并調(diào)用:
#import <MySDK/MySDK.h>
- (void)viewDidLoad
{
[super viewDidLoad];
[MyTools firstMethod];
}
打印出
2020-07-27 18:22:07.009337+0800 UITest[4196:227471] MyTools First Method
完成調(diào)用。