1.framework開始前的 理論
1).初衷
開始的理由千千萬(wàn),但殊途同歸.
(1) 提供給公司外部的人員使用, 不希望暴露內(nèi)部"高大上"的實(shí)現(xiàn)
(2) 公司內(nèi)部多個(gè)項(xiàng)目公用資源, 使用方便
(3) 模塊化榕吼、分工合作, 架構(gòu)組完成基礎(chǔ)的實(shí)現(xiàn), 功能開發(fā)工程師只需要關(guān)注功能實(shí)現(xiàn), 不需要關(guān)注底層實(shí)現(xiàn)
(4) 提高編譯速度顽素,減少少量的改動(dòng)引起的大量重復(fù)的編譯
......
2).動(dòng)態(tài)庫(kù),靜態(tài)庫(kù)
動(dòng)態(tài)庫(kù)存在形式: .framework, .dylib, .tbd
動(dòng)態(tài)庫(kù)是引用關(guān)系徒蟆,編譯時(shí)不會(huì)被拷貝到程序中胁出,程序運(yùn)行時(shí) 由系統(tǒng)動(dòng)態(tài)加載
靜態(tài)庫(kù)存在形式: .a 和 .framework
靜態(tài)庫(kù)編譯時(shí)會(huì)被完整拷貝一份到目標(biāo)程序中
動(dòng)態(tài)庫(kù)與靜態(tài)庫(kù)詳細(xì)的區(qū)別 參考:
https://my.oschina.net/shoutan/blog/786636
2.創(chuàng)建framework
1).創(chuàng)建工程
模板選擇Cocoa Touch Framework
2).編寫自定義代碼
對(duì)需要共享的內(nèi)容分模塊添加
!建庫(kù)時(shí)不得不注意的就是 swift的訪問(wèn)級(jí)別
Swift 提供了三種訪問(wèn)級(jí)別段审。這些訪問(wèn)級(jí)別相對(duì)于源文件中定義的實(shí)體全蝶,同時(shí)也相對(duì)于這些源文件所屬的模塊。
其中,函數(shù)的訪問(wèn)級(jí)別需要根據(jù)該函數(shù)的參數(shù)類型訪問(wèn)級(jí)別抑淫、返回類型訪問(wèn)級(jí)別得出绷落。如果根據(jù)參數(shù)類型和返回類型得出的函數(shù)訪問(wèn)級(jí)別不符合上下文,那么就需要明確的申明該函數(shù)的訪問(wèn)級(jí)別始苇。
代碼中的所有實(shí)體砌烁,如果你不明確的定義其訪問(wèn)級(jí)別,那么它們默認(rèn)為internal級(jí)別催式, 所以函喉, 只是在一個(gè)工程中使用, 可以不用聲明訪問(wèn)類型荣月, 該工程 均可訪問(wèn)函似。
swift 三個(gè)等級(jí)的訪問(wèn)控制權(quán)限,可以簡(jiǎn)單的通過(guò)下面的規(guī)則來(lái)進(jìn)行選擇:
- Public: 對(duì) App 或其他 framework 可見(jiàn)喉童。
- Internal: 對(duì)該 framework 可見(jiàn)
- Fileprivate: 對(duì)該編譯文件可以見(jiàn)
- Private: 對(duì)該類可見(jiàn)
具體參考文檔: http://wiki.jikexueyuan.com/project/swift/
3.編譯 真機(jī) / 模擬器 的 包
1).編譯
對(duì)工程進(jìn)行編譯(command + B)
, 找到project->products->選中EKWBaseUIKit.framework->Show In Finder
撇寞, 如下圖:
2).查看庫(kù)文件
可以看到生成的 真機(jī)和模擬器下的兩個(gè)包文件(當(dāng)前設(shè)置的模式為release模式, 所以為release模式下的兩個(gè)包文件)堂氯, 如下圖:
3). 查看庫(kù)文件支持框架
在終端通過(guò)lipo -info 靜態(tài)庫(kù)名字
可以查看動(dòng)態(tài)庫(kù)支持的架構(gòu), 如下:
可以看到當(dāng)前支持的框架包含: 有armv7
和arm64
目前iOS設(shè)備包含的架構(gòu):
模擬器:iPhone4s-iPnone5:i386蔑担; iPhone5s-iPhone7 Plus:x86_64
真機(jī): iPhone3gs-iPhone4s:armv7; iPhone5-iPhone5c:armv7s咽白; iPhone5s-iPhone7Plus:arm64
我們需要把對(duì)應(yīng)的framework引入工程中即可使用啤握, 但是我們平時(shí)可能用到真機(jī)調(diào)試,也可能使用模擬器調(diào)試晶框,來(lái)回切換framework會(huì)很繁瑣排抬,所以一般使用終端把支持真機(jī)和模擬器的framework合并成一個(gè)framework(fat版)
命令格式:lipo -create 第一個(gè).framewor下的esec文件的絕對(duì)路徑 第二個(gè).framework下的esec文件的絕對(duì)路徑 -output 最終的.framework文件路徑
操作如下:
4.使用腳本編譯
如上的單調(diào)頻繁的操作可能會(huì)讓你感覺(jué)累覺(jué)不愛(ài),xcode目前支持的腳本編譯授段,包治百病
1).創(chuàng)建Aggregate
targets點(diǎn)擊左下角 “+”蹲蒲, 添加Aggregate
2). 添加腳本文件
Run Script 中可以放入待執(zhí)行的腳本文件, 也可以放入待執(zhí)行的腳本侵贵, 但是放入待執(zhí)行腳本時(shí)届搁, 遇到過(guò)文件權(quán)限的問(wèn)題(涉及pod管理的framework), 所以此處推薦使用腳本文件的路徑代替腳本
3).使用到的腳本如下:
#!/bin/sh
#要build的target名
TARGET_NAME=${PROJECT_NAME}
if [[ $1 ]]
then
TARGET_NAME=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}_Products/"
#創(chuàng)建輸出目錄窍育,并刪除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
rm -rf "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework"
#分別編譯模擬器和真機(jī)的Framework
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
#拷貝framework到univer目錄
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_FOLDER}"
#合并framework卡睦,輸出最終的framework到build目錄
lipo -create -output "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"
#刪除編譯之后生成的無(wú)關(guān)的配置文件
dir_path="${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/"
for file in ls $dir_path
do
if [[ ${file} =~ ".xcconfig" ]]
then
rm -f "${dir_path}/${file}"
fi
done
#判斷build文件夾是否存在,存在則刪除
if [ -d "${SRCROOT}/build" ]
then
rm -rf "${SRCROOT}/build"
fi
rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"
#打開合并后的文件夾
open "${UNIVERSAL_OUTPUT_FOLDER}"
4). 腳本以及生成的framework位置
5).檢測(cè) framework支持的類型
使用lipo -info ...
查看合成的framework支持的類型 包含:i386漱抓, Plus:x86_64表锻, armv7, arm64
6.framework制作過(guò)程中的坑
1. Module
在工程中乞娄, 我們可以通過(guò)橋接文件引入需要使用的OC或者C相關(guān)的瞬逊, 但是swift動(dòng)態(tài)庫(kù)中檐迟, 是不能使用橋接文件的,比如: 需要使用CommonCrypto
里面的內(nèi)容码耐, 在工程中可以直接導(dǎo)入CommonCrypto
使用追迟, 在庫(kù)中則不能使用
這個(gè)問(wèn)題可以使用模塊化解決:
1).創(chuàng)建一個(gè)模塊化文件, 并加入對(duì)應(yīng)模塊
module CCommonCrypto [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/CommonCrypto/CommonCrypto.h"
export *
}
2). 模塊化的使用
在需要使用的文件中 輸入 import CCommonCrypto
即可使用相關(guān)內(nèi)容
3)參考文檔
https://spin.atomicobject.com/2015/02/23/c-libraries-swift/ 英文原文
http://blog.csdn.net/quentingui/article/details/44115285 翻譯
http://www.ethanwhy.com/2016/12/17/swift-framework-call-objective-c-c-language/
https://stackoverflow.com/questions/25248598/importing-commoncrypto-in-a-swift-framework/37125785#37125785
https://github.com/onmyway133/arcane
更新(2018-10-12):
xcode10中, swift增加了對(duì) CommonCrypto
的支持骚腥,在需要使用的 CommonCrypto
的swift庫(kù)中敦间,不需要Module的方式,直接添加使用即可束铭,如下:
import CommonCrypto
自己封裝的庫(kù)也可能使用了pod管理廓块,基于workspace的庫(kù)的制作將在接下來(lái)的文章中談到...
以上僅是個(gè)人使用總結(jié),歡迎批評(píng)指正補(bǔ)充~~~~~~~