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
選擇為剛才創建的Aggregate
,Device
選擇為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 需要指定要進行全部加載的庫文件的路徑,這樣的話,你就只是完全加載了一個庫文件,不影響其余庫文件的按需加載。
主要步驟大概就是這樣,如果有發現什么問題可以給我留言,希望能夠幫助大家少走一些坑。
將來的你,一定會感激現在拼命的自己,愿自己與讀者的開發之路無限美好。