Framework制作到打包

Framework制作流程

坑:由于oc的分類會覆蓋同名的方法, 在framework中一定要謹(jǐn)慎對待分類

1. 新建framework 項目

File > New > Project

create.png

2. 需要注意配置的地方

1.配置sdk運(yùn)行最低支持的iOS版本
當(dāng)sdk是為項目定制時,直接配置跟項目運(yùn)行版本一致即可;
當(dāng)sdk是封裝了開放給別的開發(fā)者使用時,使用大眾版本,如目前大多應(yīng)用都需要iOS9及以上
2.靜態(tài)庫or動態(tài)庫選擇
首先要搞清楚靜態(tài)庫和動態(tài)庫的區(qū)別,這里有介紹
在這里,我選擇了使用靜態(tài)庫的形式,配置:Build Settings > Mach-O Type 可以配置靜態(tài)庫/動態(tài)庫
3.Build Phases > Headers
Public: 需要暴露給外部的.h文件,只有在public中的.h文件,才能被外部直接使用

3.新建target測試demo

新建一個target用來測試(File > New > Target > Single View App)


屏幕快照 2020-06-15 上午10.53.39.png

如圖,Products>MyTestSDK.framework 產(chǎn)物勾選,現(xiàn)在在Demo中就可以引用SDK中的文件了

#import <MyTestSDK/TestSDKAPI.h>

屏幕快照 2020-06-15 上午11.04.06.png

4.集成第三方庫

項目開發(fā)中會使用到很多第三方庫(AFN,SD等),那么在sdk中集成第三方庫的時候最方便的是使用pods來管理了

在使用的過程中只需要sdk中和使用sdk的項目保持第三方庫的版本一致即可。

  1. 創(chuàng)建pod文件,分別添加兩個target所依賴的第三方庫(注意:使用到的相同第三方庫需要保持版本一致)

  2. 因為sdk中使用了pod管理依賴庫,所以當(dāng)sdk開發(fā)完成,提供別別人使用時,需要同時提供podspec文件,當(dāng)別人使用pod集成你的sdk的時候,podspec會指明sdk所依賴的第三方庫,pod init的時候會一并安裝

* 使用 pod spec create MyTestSDK 就可以創(chuàng)建一個名為MyTestSDK的podspec文件, 將podspec文件放在項目 ./docs/  目錄下

* podspec文件配置需要注意的地方:

  1. resource文件,sdk中需要使用的圖標(biāo)需要新建一個bundle,統(tǒng)一放在bundle中管理,

    spec.resource = "MyTestSDK.framework/*.bundle" 可以包含sdk中的所有bundle文件



  2. spec.dependency 配置,將sdk中依賴的第三方庫全都列出來

    spec.dependency 'AFNetworking'

    spec.dependency 'MJRefresh'

    spec.dependency 'YYModel'

5.framework打包腳本

sdk的打包跟需要支持的cpu架構(gòu)有關(guān),當(dāng)運(yùn)行的target選模擬器時,編譯出來的framework是支持x86_64和i386的;當(dāng)運(yùn)行的target選擇真機(jī)時,編譯出來的framework是支持arm64,armv7等架構(gòu);我們需要做的是將支持兩個架構(gòu)的可執(zhí)行文件合并,生成既支持模擬器,也支持真機(jī)運(yùn)行的包,腳本如下:


  #!/bin/sh

# 合并在真機(jī)和模擬器上編譯出的 Framework

# 如果工程名稱和Framework的Target名稱不一樣的話,要自定義FMKNAME

FMK_NAME="MyTestSDK"

# 在工程的根目錄創(chuàng)建framework的文件夾.

INSTALL_DIR="./build/MyTestSDK/${FMK_NAME}.framework"

WRK_DIR="./build"

DEVICE_DIR="./build/Build/Products/Release-iphoneos/${FMK_NAME}.framework"

SIMULATOR_DIR="./build/Build/Products/Release-iphonesimulator/${FMK_NAME}.framework"

# Clean兩個架構(gòu)的framework

xcodebuild clean -configuration "Release" -scheme ${FMK_NAME} -workspace ${FMK_NAME}.xcworkspace -sdk iphoneos

xcodebuild clean -configuration "Release" -scheme ${FMK_NAME} -workspace ${FMK_NAME}.xcworkspace -sdk iphonesimulator

# build iphoneos

xcodebuild -configuration "Release" -scheme ${FMK_NAME} -workspace ${FMK_NAME}.xcworkspace -sdk iphoneos build -derivedDataPath ${WRK_DIR}

# build simulator

xcodebuild -configuration "Release" -scheme ${FMK_NAME} -workspace ${FMK_NAME}.xcworkspace -sdk iphonesimulator build -derivedDataPath ${WRK_DIR}

# 刪除之前生成的framework

if [ -d "${INSTALL_DIR}" ]

then

rm -rf "${INSTALL_DIR}"

fi

mkdir -p "${INSTALL_DIR}"

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

# 合成同時支持真機(jī)和模擬器架構(gòu)的 framework

lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"

# 文檔, 將生成好的podspec文件拷貝到 framework目錄下

cp "./docs/MyTestSDK.podspec" "./build/MyTestSDK/"

#移除多余文件

rm -rf "./build/Build"

rm -rf "./build/Logs"

rm -rf "./build/SourcePackages"

rm -rf "./build/ModuleCache.noindex"

6. 最后的項目結(jié)構(gòu) & 需要提供的產(chǎn)物

屏幕快照 2020-06-15 上午11.50.51.png

如圖,./build/MyTestSDK/ 目錄下的 MyTestSDK.framework 和 MyTestSDK.podspec 就是需要提供給別人使用的

7. 如何集成導(dǎo)出的framework到項目中使用

只需要將第6步中導(dǎo)出的產(chǎn)物放到項目目錄下,然后使用pod集成就可以了

  1. 在項目的pod 中加入:pod 'MyTestSDK', :path => './MyTestSDK'
  2. pod install, ok 大功告成!

遇到問題及解決辦法

  1. 關(guān)于第三方庫引用,怎么避免類重名?

使用pods來管理第三方依賴庫

  1. 關(guān)于在靜態(tài)庫中使用分類時報錯 unrecognized selector sent to instanceunrecognized selector sent to instance?

    如果靜態(tài)庫中有category類,則在使用靜態(tài)庫的項目配置中【Other Linker Flags】需要添加參數(shù)【-ObjC]或者【-all_load】。

  2. 不能斷點調(diào)試framework中的源碼?
    調(diào)試中發(fā)現(xiàn)在framework的源碼打斷點沒有效果, 排查后發(fā)現(xiàn)是因為 framework target的 Generate Debug Symbols 設(shè)置為NO, 導(dǎo)致的, 改成YES即可 (Generate Debug Symbols 對app target也是相同的效果, 可以縮小framework的包大小, 但是不會生成調(diào)試信息, 導(dǎo)致不能斷點調(diào)試)

  3. 使用lipo合并真機(jī)&模擬器framework時報錯: have the same architectures (arm64) and can't be in the same fat output file
    在Xcode12之前:
    編譯模擬器靜態(tài)庫支持i386 x86_64兩架構(gòu)
    編譯真機(jī)靜態(tài)庫支持armv7 arm64兩架構(gòu)
    使用lipo -create -output命令可以將兩個庫合并成一個支持模擬器和真機(jī)i386 x86_64 armv7 arm64四種架構(gòu)的靜態(tài)庫。

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

---> 解決: 在 Build Settings -> Excluded Architectures 設(shè)置 Any iOS Simulator SDK : arm64
在打包時, 模擬器上的庫就不會在支持arm64架構(gòu)了, 合并也就沒問題了
---> 解決2: 可以使用 lipo xxx.a -remove arm64 -output xxx_no64.a, 將模擬器靜態(tài)庫中的arm64移除, 然后再進(jìn)行合并

  1. 問題4中連帶出的問題, 經(jīng)過問題4中打包出來的framework同時支持了 真機(jī):arm64、armv7, 模擬器:i386、x86_64 這4種架構(gòu), 但是在Xcode13(目前使用的13)或以上使用時, 在模擬器上編譯會報錯: in XXX.a(XXXXXXX.o), building for iOS Simulator, but linking in object file built for iOS, for architecture arm64
    ---> 模擬器運(yùn)行需要支持模擬器的arm64, 但是靜態(tài)庫中沒有, 所以報錯了
    ---> 解決: 在 Build Settings -> Excluded Architectures 設(shè)置 Any iOS Simulator SDK : arm64 (Debug模式, 因為運(yùn)行的時候一般是設(shè)置的debug)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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