iOS開發中,有時候需要將一些工具包裝起來,做成sdk提供給客戶使用,制作過程可以分為兩種。一種是制作靜態庫.a文件,一種是制作成framework文件。前者操作起來簡單,但是提供給客戶時比較麻煩,需要提供頭文件。後者使用簡便,可以直接導入,但是制作較為麻煩。
蘋果在iOS8之前都不支持動態庫framework方法,所以這裡說的framework實質上都是靜態庫文件。如果有什麼理解和整理錯誤的地方,歡迎大家指出問題所在。
這篇文章主要記錄創建framework的方法。創建framework也有兩種方法,一種是Xcode6之前的制作方法,一種是Xcode6之後的制作方法。這篇博客先講解最新版本Xcode7制作framework的方法。
Xcode6就已經提供了動態庫的制作方法。這裡還是以Xcode7為例,兩者的操作步驟是相同的。新建一個Project,選擇iOS下的Framework & Library選項:
創建之後,選擇你創建的Targets,在BuildSetting中搜索Mach-O,將之設置為Static Library:
然後這裡開始寫一個類來制作framework,提供給另一個項目進行測試,當新建好一個類文件的時候,需要在默認存在的ZYXTestFramework.h中將新建的類的頭文件暴露出來,否則在另一個項目中導入頭文件時會出現“Missing XXXXX”的警告。
在新建的類中寫一個測試方法,打印傳遞過來的字符串,頭文件暴露出該方法:
完成之後,選擇Targets下的Build Phase選項,還需要將新創建的類的頭文件暴露給使用framework的開發者調用。Headers下有三個選項Public,Private,Projects。可能中間的Private的名字會讓人產生一些困惑,Private並不表明是私有的,其還是暴露了一些東西,Projects才是表明是私有的文件(該解釋是從網上一篇教程中看到的,目前也不是太明確,不過一般來說還是使用Public和Projects這兩個)。將ZYXFrameworkTest.h移動到Public下。
此時已經可以進行編譯操作了,但是這裡需要說明:我們制作的framework針對的iPhone手機的架構不只一種,一般模擬器使用的是x86 64與i386,而真機主要是arm64和armv7。armv7s很多sdk都沒有特定去編譯他,比如說facebook,我查看他們支持的架構未包括armv7s。網上有些教程說需要更改下圖中的兩個選項,其實對於這篇博文來說是沒有必要的。
在編譯時,設置為Release狀態來進行framework的生成。這裡先生成支持模擬器的Release版本,選擇EditScheme,將run狀態下的Debug改為Release。
運行,生成framework。可以查看生成的framework支持的架構,打開生成的framework在Finder中的位置,拖拽到終端,使用lipo命令來查看支持的架構。其中ZYXTestFramework文件實質上是靜態.a文件。
可以看見支持的架構為i386何x86 64。接著再為真機生成一次framewok,因為手邊沒有真機,沒辦法截圖。生成步驟與上述操作一樣,只要換成真機設備就可以了。
最終生成之後需要合並兩個文件,使之支持4個架構,在合並時,操作的就是上面所說的實質上是靜態.a的ZYXTestFramework文件。在終端下執行lipo -create (模擬器生成的ZYXTestFrameWork路徑) ( 真機生成的路徑 ) -outfile 合並的之後的路徑和名稱
上述生成操作也可以直接使用腳本來執行,在Xcode中新建一個Target,選擇Aggregate。該Target可以用來執行腳本生成項目。
新建完畢後,在Build Phase下點擊+號,選擇New copy Run scripts,然後添加一段腳本
腳本內容如下:
set -e
# 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}"
注意:使用這段腳本時“xcodebuild -configuration"Release"-target"${FMK_NAME}"-sdk iphoneos clean build”該段腳本直接執行了真機生成,所以就像使用真機調試一樣,需要一個簽名證書。否則Build會失敗。
生成時需要調整Target,對Aggregate執行run操作。最終會在當前項目目錄中創建一個Products目錄,在該目錄下會有合成後的framework。 但是會有一個_codeSignature文件夾,應該是真機調試簽名生成的文件夾。因為我看facebook的SDK中的framework中沒有這個文件夾,所以不知道刪除這個_codeSignature會不會有影響。使用者在使用這個framework時會不會也對這個framework進行簽名,如果有人能解惑,非常感謝。
將生成後的framework放入測試項目中,導入頭文件,進行測試。因為身邊沒有手機,所以直接用的模擬器測試的,這也是上面那個問題沒有驗證的原因。最終測試結果如下:(好像圖片上傳不了了,導入頭文件和調用什麼的都沒截圖了,太大)
可以看見最終是成功調用到framework中的api。這是Xcode7生成framework的方法,我個人覺得最終還是靜態的庫,應該不會被蘋果拒絕,和facebook對比發現就是多了一個_codeSignature文件夾,這個app真機簽名文件夾刪除之後不知道有沒有影響。