iOS 最全動(dòng)態(tài)庫(kù)/靜態(tài)庫(kù)制作 Framework/.a

一、靜態(tài)庫(kù)

1.創(chuàng)建靜態(tài)庫(kù)工程

Xcode -> Create a new Xcode project -> iOS -> Static Library
image.png

2.將代碼導(dǎo)入工程 選擇Create groups(邏輯路徑)
image.png

3.配置一些設(shè)置

(1)Build Active Architecture Only

Build Active Architecture Only 設(shè)置為NO的意思是當(dāng)前打包的.a支持所有的設(shè)備.否則打包時(shí)只能用當(dāng)前版本的模擬器或真機(jī)運(yùn)行.
image.png

(2)Dead Code Stripping

Build Settings中Link下面的Dead Code Stripping設(shè)置為NO:先不進(jìn)行死代碼剝離。
image.png

(3)設(shè)置.a最低支持的版本
image.png

3.暴露頭文件(.h)以供SDK使用者調(diào)用

(1)Bulid Phases -> Copy Files -> + 將所有.h Copy進(jìn)工程
image.png

(2.1)創(chuàng)建Headers

Bulid Phases -> + -> New Headers Phase
image.png

(2.2)Headers -> + 導(dǎo)入所有頭文件
image.png

(2.3)將所有需要暴露的頭文件拖到public
image.png

4.在模擬器和真機(jī)中run四種模式

① debug 模式 模擬器運(yùn)行
② debug 模式 真機(jī)運(yùn)行
③ release 模式 模擬器運(yùn)行
④ release 模式 真機(jī)運(yùn)行
(1)X86_64 和 arm64 切換
使用模擬器運(yùn)行,制作的SDK是X86_64
使用真機(jī)運(yùn)行,制作的SDK是arm64
(2)編譯配置
蘋果架構(gòu)分為x86_64(模擬器) arm64
蘋果包分為 Debug 和 Release

一般都是使用arm64
調(diào)試時(shí),使用Debug包,上線使用Release

(1)Debug 和 Release 切換

Release: 選中工程->Edit Scheme->Run->Build Configuration->Release

Debug: 選中工程->Edit Scheme->Run->Build Configuration->Debug
image.png

image.png

(2)Run工程獲取SDK

Clean: Product -> Clean Build Folder
Run工程后,在Product->Show Bulid Folder in Finder -> Products 中獲取SDK

通過Product找到位置:


image.png

靜態(tài)庫(kù)是以.a后綴結(jié)尾,動(dòng)態(tài)庫(kù)是以.framework 后綴結(jié)尾

使用真機(jī)運(yùn)行可能出現(xiàn)的問題:
image.png

這是由于真機(jī)的系統(tǒng)版本低于工程設(shè)置的最低版本

修改工程的最低版本
image.png

5.模擬器和真機(jī)通用架構(gòu)模式合并

(1)查看debug真機(jī)和模擬器架構(gòu)

lipo -info 路徑
a.查看debug真機(jī)
image.png
b.查看debug模擬器
image.png

(2)移除模擬器包含arm64架構(gòu)

在合并模擬器和真機(jī)架構(gòu)時(shí),如果.a中都包含arm64架會(huì)導(dǎo)致真機(jī)和模擬器無法合并。報(bào)錯(cuò):have the same architectures (arm64) and can't be in the same fat output file。

XCode12之前:
編譯模擬器靜態(tài)庫(kù)支持i386 x86_64兩架構(gòu)
編譯真機(jī)靜態(tài)庫(kù)支持armv7 arm64兩架構(gòu)
使用lipo -create -output命令可以將兩個(gè)庫(kù)合并成一個(gè)支持模擬器和真機(jī)i386 x86_64 armv7 arm64四種架構(gòu)的胖子庫(kù)。

然而XCode12編譯的模擬器靜態(tài)庫(kù)也支持了arm64,導(dǎo)致出現(xiàn)真機(jī)庫(kù)和模擬器庫(kù)不能合并的問題。

解決方案1:

如果有靜態(tài)庫(kù)工程:Build Settings -> Excluded Architectures里按照這樣設(shè)置一下,再編譯合并就不會(huì)報(bào)錯(cuò)了。
image.png
解決方案2:如果手里只有.a或.framework文件

使用lipo remove命令將模擬器庫(kù)的arm64架構(gòu)移除

lipo 模擬器路徑.a -remove arm64 -output 模擬器路徑.a
deDerivedoate.png

(3)合并模擬器和真機(jī)架構(gòu)

a.終端方式
 sudo lipo -create [模擬器路徑] [真機(jī)路徑] -output [合成路徑/文件名(自定義)]

合并成功如下:
image.png

查看.a支持設(shè)備架構(gòu) 模擬器+真機(jī)
image.png
b.腳本方式

(1)通過target創(chuàng)建 Aggregate
TARGETS.png
Multiplstform.png

(2)新建New Run Script Phase


Resource Tags Build Settings Build Phases Build Rules.png

(3).a合并腳本
# Type a script or drag a script file from your workspace to insert its path.
if [ "${ACTION}" = "build" ]
then
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.a

DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.a

SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.a

# 如果真機(jī)包或模擬包不存在,則退出合并
if [ ! -d "${DEVICE_DIR}" ] || [ ! -d "${SIMULATOR_DIR}" ]
then
exit 0
fi

# 如果合并包已經(jīng)存在,則替換
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi

mkdir -p "${INSTALL_DIR}"

cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"

# 使用lipo命令將其合并成一個(gè)通用.a  
# 最后將生成的通用.a放置在工程根目錄下新建的Products目錄下  
lipo -create "${DEVICE_DIR" "${SIMULATOR_DIR}" -output "${INSTALL_DIR}"

#合并完成后打開目錄
open "${SRCROOT}/Products"

fi

如下圖:
Type soript or drop a soript f1le ro Ur workspase to 1nsert t5 path.png

寫好腳本后執(zhí)行run,會(huì)自動(dòng)在在Product->Show Bulid Folder in Finder -> Products 生成靜態(tài)庫(kù)。

6.使用靜態(tài)庫(kù)

(1)文件(.h、.m)中封裝好方法以及合并好生成的.a靜態(tài)庫(kù)

image.png
image.png
image.png

(2)將.h文件和.a庫(kù)拖到需要集成的項(xiàng)目中

\color{red}{注意:1.如果要給別人調(diào)用靜態(tài)庫(kù)中的方法,那就必須將方法暴露到.h文件中,并復(fù)制一份.h文件供項(xiàng)目調(diào)用。}
\color{red}{2.自己制作的靜態(tài)庫(kù)中包含了另外的靜態(tài)庫(kù),那需要將新制作的靜態(tài)庫(kù)和另外包含的靜態(tài)庫(kù)一并復(fù)制到項(xiàng)目中使用}

image.png

(3)將.h文件和.a庫(kù)加到Build Phases中

a.將frameWorkTest1加到Compile Sourceas中
image.png
B.生成的.a靜態(tài)庫(kù)加在Link Binary With Libaries
image.png

(4)調(diào)用靜態(tài)庫(kù)方法

image.png
image.png
image.png

可能遇到的問題

報(bào)錯(cuò)2 duplicate symbols for architecture arm64

解決方案:
2 duplicate symbols for architecture arm64 常見問題,是在導(dǎo)入第三方SDK的時(shí)候出現(xiàn)的。
究其原因一定是SDK中包含了工程中原本存在的某個(gè)類:全文搜索找到此類,無用的話將其刪除,有用改變名字即可。

二、動(dòng)態(tài)庫(kù)

1.創(chuàng)建動(dòng)態(tài)庫(kù)工程

Xcode -> Create a new Xcode project -> iOS -> Framework
Pasted Graphic 7.png

2.將代碼導(dǎo)入工程 選擇Create groups(邏輯路徑)
ehoose eplions for adding these fikes.png

(1)本例創(chuàng)建動(dòng)態(tài)庫(kù)的名字為dynamicFrameWork,項(xiàng)目會(huì)自動(dòng)生成一個(gè)名為dynamicFrameWork的頭文件
dynamicFrameWork.png
w Created by Se sn 2921129.png

(2)在framework自動(dòng)生成的dynamicFrameWork.h文件中導(dǎo)入你想用的頭文件,如下圖:
wimport &FoundationFoundation.png

(3)不在framework自動(dòng)生成的dynamicFrameWork.h文件中聲明頭文件,在新工程使用時(shí)會(huì)報(bào)警告,如下圖:

aimport “ViewController.h?.png

1.雖然編譯沒問題,但作為一個(gè)強(qiáng)迫癥患者,還是在自動(dòng)生成的.h文件中把需要用到的頭文件全部導(dǎo)入。
2.使用時(shí)更加方便,只要#import <dynamicFrameWork/dynamicFrameWork.h>即可使用動(dòng)態(tài)庫(kù)中的包含的全部文件,更加節(jié)省代碼。

大家可自定義自己的UI界面、功能或邏輯。代碼寫完后,可在路徑TARGETS->Build Phases->Headers下將你需要暴露給外面調(diào)用的頭文件添加到Public下面即可將文件拖入工程(步驟4中會(huì)說)

3.配置一些設(shè)置

(1)Build Active Architecture Only

Build Active Architecture Only 設(shè)置為NO的意思是當(dāng)前打包的.a支持所有的設(shè)備.否則打包時(shí)只能用當(dāng)前版本的模擬器或真機(jī)運(yùn)行.
Basic.png

(2)Dead Code Stripping

Build Settings中Link下面的Dead Code Stripping設(shè)置為NO:先不進(jìn)行死代碼剝離。
Basic Customized.png

(3)Mach-O Type(庫(kù)性質(zhì))

簡(jiǎn)單總結(jié)為
庫(kù)性質(zhì)決定庫(kù)加載到運(yùn)行時(shí)內(nèi)存的時(shí)機(jī)、加載的庫(kù)范圍、庫(kù)的共享權(quán)限
mach -O Type:一種文件格式,Mach Object文件格式,是Mac上的可執(zhí)行文件類型 或者 目標(biāo)文件(.o)。
以開發(fā)者制作三方庫(kù)的場(chǎng)景為例解釋:

Executable:  `靜態(tài)庫(kù)`,輸出二進(jìn)制
Dynamic Library:`動(dòng)態(tài)非共享庫(kù)`,輸出動(dòng)態(tài)鏈接庫(kù)非共享庫(kù),程序`運(yùn)行`時(shí)鏈接到`內(nèi)存`,大部分場(chǎng)景下不可共享;app extension、部分macOS場(chǎng)景下可以共享
Bundle:`動(dòng)態(tài)非共享庫(kù)`,和Dynamic Library相近,不過需要手動(dòng)調(diào)用函數(shù)加載
Static Library:  `靜態(tài)庫(kù)`,輸出靜態(tài)鏈接庫(kù),程序`編譯`時(shí)拷貝到`內(nèi)存`
Relocatable Object File:`靜態(tài)庫(kù)`,和Static Library類似,但體積更小

從結(jié)構(gòu)上看:

1.Framework格式的庫(kù)只是比Static Library格式的庫(kù)多出一個(gè)文件夾,擁有一個(gè)獨(dú)立的工作區(qū)
2.Framework格式的庫(kù)中嵌入的依賴庫(kù)可以和app環(huán)境的依賴庫(kù)相同,并且不會(huì)產(chǎn)生duplicate symbol,因?yàn)镕ramework有獨(dú)立的運(yùn)行環(huán)境
3.Static Library格式的庫(kù)中的依賴庫(kù)和app環(huán)境依賴庫(kù)相同時(shí)會(huì)有依賴沖突
4.Static Library格式的庫(kù)的依賴的方法可以不實(shí)現(xiàn),但Framework格式的庫(kù)依賴的方法必須實(shí)現(xiàn)(objc)
5.Static Library格式的庫(kù)不可包含圖片等資源文件
6.Static Library格式的庫(kù)的庫(kù)在打包時(shí)會(huì)直接編譯進(jìn)app的二進(jìn)制執(zhí)行文件,F(xiàn)ramework格式的庫(kù)被打包進(jìn)沙盒;如果觀察過Product包內(nèi)容時(shí)會(huì)發(fā)現(xiàn)使用<Static Library格式的庫(kù)>或者<Framework格式的庫(kù)且(mach -O Type = Static Library)>不會(huì)出現(xiàn)在Frameworks文件夾中,是因?yàn)榫幾g進(jìn)了app的二進(jìn)制執(zhí)行文件
7.開發(fā)者簽名的Dynamic Library性質(zhì)的庫(kù)時(shí)在app extension中共享或者在macOS部分場(chǎng)景下共享;蘋果官方的動(dòng)態(tài)庫(kù)有共享權(quán)限
8.制作三方庫(kù)在考慮Static Library格式的庫(kù)庫(kù)或者Framework格式的庫(kù)時(shí):依賴圖片資源,使用Framework格式的庫(kù);想要擁有完整的依賴關(guān)系,使用Framework格式的庫(kù),此時(shí)外界可能需要剔除Framework格式的庫(kù)之外的依賴庫(kù),而采用Framework格式的庫(kù)內(nèi)的依賴庫(kù),否則雖然不會(huì)產(chǎn)生依賴沖突,但會(huì)增加包大小

Statlo Ubrary.png
1.選擇Dynamic Library生成動(dòng)態(tài)庫(kù),Static Library生成的是靜態(tài)庫(kù)。
2.由于iOS8之后才允許使用插入動(dòng)態(tài)庫(kù),所以網(wǎng)上大部分教程在選MachO-Type的時(shí)候選擇的是Static Library。但是.a靜態(tài)庫(kù)和靜態(tài)framework無法訪問庫(kù)中的資源圖片的。所以自己創(chuàng)建的framework如果想訪問庫(kù)中的資源文件,那么必須要是動(dòng)態(tài)庫(kù)。
3.自建動(dòng)態(tài)庫(kù)手動(dòng)拖入的工程后,必須選擇embed選項(xiàng),否則的話,啟動(dòng)即崩潰。
4.靜態(tài)庫(kù)中關(guān)聯(lián)的對(duì)象無法用KVO進(jìn)行觀察,不會(huì)觸動(dòng)KVO回調(diào)方法。
5.理解一下靜態(tài)庫(kù)和動(dòng)態(tài)庫(kù)點(diǎn)擊地址進(jìn)入

(4)設(shè)置.framework最低支持的版本

targ.png

不設(shè)置版本打出來的真機(jī)的framework只包含arm64架構(gòu),模擬器的framework只包含arm64和x86_64架構(gòu)

(5)Link With Standard Libraries

Build Settings中Link下面的Link With Standard Libraries設(shè)置NO:避免重復(fù)鏈接
image.png

4.暴露頭文件(.h)以供SDK使用者調(diào)用

TARGETS —> Build Phases -》 Headers

把要暴露給別人的文件,從Project 拖動(dòng)到Public中既可
Sianing & Capabstes.png

5.在模擬器和真機(jī)中run四種模式

① debug 模式 模擬器運(yùn)行
② debug 模式 真機(jī)運(yùn)行
③ release 模式 模擬器運(yùn)行
④ release 模式 真機(jī)運(yùn)行
(1)X86_64 和 arm64 切換
使用模擬器運(yùn)行,制作的SDK是X86_64
使用真機(jī)運(yùn)行,制作的SDK是arm64
(2)編譯配置
蘋果架構(gòu)分為x86_64(模擬器) arm64
蘋果包分為 Debug 和 Release

一般都是使用arm64
調(diào)試時(shí),使用Debug包,上線使用Release

(1)Debug 和 Release 切換

Release: 選中工程->Edit Scheme->Run->Build Configuration->Release

Debug: 選中工程->Edit Scheme->Run->Build Configuration->Debug
, dynamicFrameWork.png
Wan for the erecvtable to be launched.png

(2)Run工程獲取SDK

Clean: Product -> Clean Build Folder
Run工程后,在Product->Show Bulid Folder in Finder -> Products 中獲取SDK

通過Product找到位置:
dynamicFrameWork.framework.png

5.模擬器和真機(jī)通用架構(gòu)模式合并

(1)查看debug真機(jī)和模擬器架構(gòu)

lipo -info 路徑
a.查看debug真機(jī)
Lost loain Wed Dec 174740 on tty$002.png
b.查看debug模擬器
ipo -info Users.png

(2)移除模擬器包含arm64架構(gòu)

在合并模擬器和真機(jī)架構(gòu)時(shí),如果.a中都包含arm64架會(huì)導(dǎo)致真機(jī)和模擬器無法合并。報(bào)錯(cuò):have the same architectures (arm64) and can't be in the same fat output file。
XCode12之前:編譯模擬器靜態(tài)庫(kù)支持i386 x86_64兩架構(gòu)編譯真機(jī)靜態(tài)庫(kù)支持armv7 arm64兩架構(gòu)使用lipo -create -output命令可以將兩個(gè)庫(kù)合并成一個(gè)支持模擬器和真機(jī)i386 x86_64 armv7 arm64四種架構(gòu)的胖子庫(kù)。
然而XCode12編譯的模擬器靜態(tài)庫(kù)也支持了arm64,導(dǎo)致出現(xiàn)真機(jī)庫(kù)和模擬器庫(kù)不能合并的問題。

解決方案1:

如果有動(dòng)態(tài)庫(kù)工程:Build Settings -> Excluded Architectures里按照這樣設(shè)置一下,再編譯合并就不會(huì)報(bào)錯(cuò)了。
image.png
解決方案2:如果手里只有.framework文件

使用lipo remove命令將模擬器庫(kù)的arm64架構(gòu)移除

lipo 模擬器路徑.framework -remove arm64 -output 模擬器路徑.framework
MscBook-.png

(3)合并模擬器和真機(jī)架構(gòu)

a.終端方式
 sudo lipo -create [模擬器路徑] [真機(jī)路徑] -output [合成路徑/文件名(自定義)]

合并成功如下:
圖 dynamicFrameWorkTest.png
b.腳本方式

(1)通過target創(chuàng)建 Aggregate


image.png
image.png

(2)在Dependencies中添加dynamicFrameWork
Se source Tags Buld Serthos Buld Pases Buss Rudes.png
ROJECT.png

(3)新建New Run Script Phase
Resource Tags Build Settings Bulld Phasos.png

(4).framework合并腳本

# Type a script or drag a script file from your workspace to insert its path.
if [ "${ACTION}" = "build" ]
then
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework

DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework

SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework

# 如果真機(jī)包或模擬包不存在,則退出合并
if [ ! -d "${DEVICE_DIR}" ] || [ ! -d "${SIMULATOR_DIR}" ]
then
exit 0
fi

# 如果合并包已經(jīng)存在,則替換
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi

mkdir -p "${INSTALL_DIR}"

cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"

# 使用lipo命令將其合并成一個(gè)通用framework  
# 最后將生成的通用framework放置在工程根目錄下新建的Products目錄下  
lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"

#合并完成后打開目錄
open "${SRCROOT}/Products"

fi

如下圖:
T scriet or drag a ssript 5e ree Your workspace to.png

寫好腳本后執(zhí)行run,編譯新 target,會(huì)自動(dòng)在在Product->Show Bulid Folder in Finder -> Products 生成動(dòng)態(tài)庫(kù)。

6.使用動(dòng)態(tài)庫(kù)

(1)獲取真機(jī)framework

在Product->Show Bulid Folder in Finder -> Products 中獲取SDK,并拖入到新工程調(diào)用。
dynamicFrameWork.framework.png
a.如果你的framework合并了真機(jī)和模擬器會(huì)報(bào)錯(cuò),如下:
Building for iOS, but the linked and embedded framework 'dynamicFrameWork.framework' was built for iOS + iOS Simulator.

解決方案:
將合并了模擬器和真機(jī)的framework剝離,只用真機(jī)的framework即可。如(1)圖

b.注意事項(xiàng)

1.動(dòng)態(tài)庫(kù)的上架,只能上架真機(jī)版本,因?yàn)槠浣Y(jié)構(gòu)不一樣,是編譯后的文件。因?yàn)樘O果是不會(huì)讓你上傳模擬器版本到線上商店,這樣會(huì)憑空增加app大小。
2.所以不需要合并真機(jī)和模擬器,選擇真機(jī)架構(gòu)framework拖入工程使用即可。如果動(dòng)態(tài)庫(kù)合并了真機(jī)和模擬器,編譯會(huì)報(bào)錯(cuò)。(忽略步驟5.模擬器和真機(jī)通用架構(gòu)模式合并)
3.靜態(tài)庫(kù)不同,靜態(tài)庫(kù)是會(huì)再通過編譯,生成執(zhí)行文件的??梢院喜⒄鏅C(jī)和模擬器。

提示:如果你非得用合并了的模擬器和真機(jī)的framework,你聲明只能用#import "",不能使用#import <>。如下:(不建議這么弄,不需要的直接忽略這條)

#import "dynamicFrameWork.framework/Headers/dynamicTestView.h"
#import "dynamicFrameWork.framework/Headers/testFrameWork.h"
(2)配置framework的Embed屬性
Genera Signing & Copablnes RSOUrCe Teps Into Buld Settings Build Phases Buld Rules.png
(3)調(diào)用動(dòng)態(tài)庫(kù)中的文件
(a).dynamicTestView工程(.m)
image.png
(b).testFrameWork工程(.h/.m)

.h文件:
image.png

.m文件:
image.png
(c).開始調(diào)用動(dòng)態(tài)庫(kù)
image.png

可能遇到的問題
image.png

Reason:image not found

解決方案:Builld Phases->xxx.framework修改 Status 修改為 Optional
image.png
最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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