【iOS 開發】將自己的框架打包成 Framework 的方法

Framework

最近需要將公司項目中的公共代碼給提取出來,打包成 Framework 來使用,這樣可以使得我們的公共代碼易于分享,并且可以在多個工程中易于復用,而且將這些代碼給別人使用時,可以隱藏實現細節,控制公開的頭文件,下面分享一下打包成 Framework 的步驟。

如果你要打包的代碼需要用到別的第三方庫的話,可以轉到我的另一篇文章:【iOS 開發】打包 Framework 時使用 CocoaPods 引入第三方庫的方法


創建 Framework 工程

1. 創建打包工程

  • 打開 Xcode 新建一個工程,選擇 Framework & Libray 選項中的 Cocoa Touch Framework ,這里說一下我的 Xcode 版本是 8.3.2
創建工程
  • 因為要打包所需的文件,所以這里我自己創建了一個測試類,在實際的打包過程中,直接把需要打包的所有文件拖到該工程中即可。
測試類

2. 添加公開頭文件

  • 選中 Target ,選擇 Build Phases - Headers ,可以看出有三個選項,分別是 Public 、Private 、Project ,把需要公開給別人的 .h 文件拖到 Public 中,把不想公開的,即為隱藏的 .h 文件拖到 Project 中。
Headers
  • 完成上述步驟之后,在默認生成的 .h 文件中,我的是 TestFramework.h ,把所有需要暴露的 .h 文件都用 #import <TestFramework/PublicHeader.h>引入,記住一定要將所有需要暴露的 .h 文件都引入,也就是上面 Headers - Public 中加的所有 .h 文件,不然編譯后生成的 .framework 在引用的時候會有警告。
引入頭文件

3. 更改設置參數

  • 選中 Target ,選擇 Build Settings ,在 Architectures 下增加 armv7s
更改設置參數
  • 選中 Target ,選擇 Build Settings ,在搜索欄搜索 Mach-O Type ,將 Mach-O Type 修改為 Static Library
更改設置參數

工程打包成 Framework

1. 創建 Aggregate

  • 新建一個 Target ,選擇 Cross-platform - Aggregate ,名字隨便起一個。
創建 Aggregate
  • 選中新建的 Target ,點擊 Build Pharas 中的 + ,選擇 New Run Script Phase
New Run Script Phase
  • 點開 Run Script ,添加以下的腳本代碼。
# Sets the target folders and the final framework product.
# 如果工程名稱和Framework的Target名稱不一樣的話,要自定義FMKNAME
# 例如: FMK_NAME = "MyFramework"
FMK_NAME=${PROJECT_NAME}
# Install dir will be the final output to the framework.
# The following line create it in the root folder of the current project.
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build
# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
open "${INSTALL_DIR}"
Run Script

2. 編譯所有文件

  • 按照下圖將編譯的 Target 選擇為剛才創建的 AggregateDevice 選擇為 Generic iOS Device ,然后按下 Command + B 開始編譯。
編譯文件
  • 編譯完成后會自動彈出已經創建完成的 Framework 包內容,最終打包完的 .framework 會在項目下的 Products 文件夾下。
Products

測試打包完的 Framework

  • 新建一個測試工程 TestDemo ,將打包完的 TestFramework.framework 拖到工程中,測試一下剛才創建的 TestClass 類,可以看到信息打印出來了,測試成功。
測試工程
  • 如果使用打包完的 Framework 有出現崩潰的情況,可以考慮在項目 Other linker flags 中加入一些參數,下面介紹三個常用參數:
-ObjC:加了這個參數后,鏈接器就會把靜態庫中所有的 Objective-C 類和分類都加載到最后的可執行文件中。

-all_load:會讓鏈接器把所有找到的目標文件都加載到可執行文件中,但是千萬不要隨便使用這個參數!假如你使用了不止一個靜態庫文件,然后又使用了這個參數,那么你很有可能會遇到 ld: duplicate symbol 錯誤,因為不同的庫文件里面可能會有相同的目標文件,所以建議在遇到 -ObjC 失效的情況下使用 -force_load 參數。

-force_load:所做的事情跟 -all_load 其實是一樣的,但是 -force_load 需要指定要進行全部加載的庫文件的路徑,這樣的話,你就只是完全加載了一個庫文件,不影響其余庫文件的按需加載。

主要步驟大概就是這樣,如果有發現什么問題可以給我留言,希望能夠幫助大家少走一些坑。

將來的你,一定會感激現在拼命的自己,愿自己與讀者的開發之路無限美好。

我的傳送門: 博客簡書微博GitHub

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容