一耳奕、制作framework
1.創(chuàng)建APP工程稚新,用來開發(fā)framework和測試
2.創(chuàng)建framework的Target襟沮,根據(jù)項目需要來命名锥惋,此處命名為TestSDK,創(chuàng)建步驟如下:
3.工程使用pod管理依賴三方庫
使用終端cd到工程根目錄开伏,執(zhí)行命令
pod init
膀跌,打開生成的Podfile文件,添加framework所需的第三方庫固灵,如pod 'SnapKit'
捅伤,并執(zhí)行pod install
,然后打開TestDemo.xcworkspace
文件
4.配置framework
設置支持版本
取消只編譯當前架構
移除重復的架構
真機和模擬器編譯后巫玻,framework中arm64架構重復丛忆,會導致合并失敗困介,所以移除模擬器中的arm64架構
設置編譯選項優(yōu)化,給framework包瘦身
設置類型為靜態(tài)庫
Scheme切換到TestDemo蘸际,設置release
5.開發(fā)功能代碼
如果讓類和方法讓外界可調(diào)用,需要用權限修飾徒扶,使用public粮彤,如果要提供OC調(diào)用,要使用@objc修飾
swift 不像OC可以暴露接口姜骡,在swift中 要想給別的工程調(diào)用接口导坟,記得在類,方法或?qū)傩郧凹觩ublic圈澈。
swift權限控制符:
open 權限最大惫周,可以被外界模塊訪問,繼承重寫
public 可以被外界工程訪問
internal 默認文件創(chuàng)建時的權限康栈,可以在本工程的訪問
private 只可以在創(chuàng)建的文件內(nèi)訪問
5.1.framework中的資源文件的使用
1).圖片資源
extension UIImage {
class func ex_image(named name: String) -> UIImage {
//圖片放到 framework 的 bundle 中可使用
let bundleName = "TestSDK.framework/ImageBundle.bundle/\(name)"
if let image = UIImage(named: bundleName) {
return image
}
return UIImage()
}
}
2).文件資源
文件資源也可以放在bundle中递递,同樣的調(diào)用方式
var filterData: [FilterModel] = load("filters.json")
func load<T: Decodable>(_ fileName: String, as type: T.Type = T.self) -> T {
let data: Data
let mainBundle = Bundle.main.path(forResource: "TestSDK.framework/ImageBundle", ofType: "bundle")
let fileBundle = Bundle.init(path: mainBundle ?? "")
let path = fileBundle?.path(forResource: fileName, ofType: nil) ?? ""
let file = URL(fileURLWithPath: path)
do {
data = try Data(contentsOf: file)
} catch {
fatalError("無法初始化\(fileName)文件")
}
do {
let decoder = JSONDecoder()
return try decoder.decode(T.self, from: data)
} catch {
fatalError("無法解析\(fileName)文件")
}
}
6.添加生成最終需要發(fā)布的framework的腳本
說明:關于framework編譯和合并的腳本,我還是比較喜歡以下的方式啥么,簡單粗暴登舞。
像新建一個shell腳本的target我也試過,framework中沒有依賴三方還行悬荣,像我這種依賴三方庫的菠秒,shell運行不通過,三方庫會報錯
# 真機和模擬器framework合并腳本
# 選中framework氯迂,分別在真機和模擬器編譯成功即可
if [ "${ACTION}" = "build" ]
then
# 定義framework名稱(替換為自己定義的名字即可)
SDK_NAME=TestSDK
# 輸出路徑
INSTALL_DIR=${SRCROOT}/Products/${SDK_NAME}.framework
# 真機路徑
DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${SDK_NAME}.framework
# 模擬器路徑
SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${SDK_NAME}.framework
# 如果輸出路徑已存在践叠,則刪除
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
# 創(chuàng)建輸出路徑
mkdir -p "${INSTALL_DIR}"
# 如果真機framework和模擬器framework都存在
if [ -d "${DEVICE_DIR}" ] && [ -d "${SIMULATOR_DIR}" ]
then
# 拷貝真機framework到輸出路徑
cp -r "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# 拷貝模擬器framework中的modules到輸出路徑
cp -r "${SIMULATOR_DIR}/Modules/${SDK_NAME}.swiftmodule/" "${INSTALL_DIR}/Modules/${SDK_NAME}.swiftmodule"
# 合并真機framework和模擬器framework
lipo -create "${DEVICE_DIR}/${SDK_NAME}" "${SIMULATOR_DIR}/${SDK_NAME}" -output "${INSTALL_DIR}/${SDK_NAME}"
fi
fi
7.生成framework
選中TestSDK,分別在真機和模擬器編譯一次即可嚼蚀,然后在項目的根目錄中禁灼,Products文件夾里會有最終的framework
二、發(fā)布framework
cocoapods發(fā)布私有庫的大致流程為:
1轿曙、GitHub上創(chuàng)建一個私有索引庫匾二,這個索引庫存放的都是私有庫的路徑
2、GitHub拳芙、碼云或者Coding等上創(chuàng)建一個私有庫察藐,存放的是整個私有庫的所有源碼
3、把私有庫的.podspec文件push到私有索引庫中
4舟扎、把私有索引庫更新到本地repo中
1.創(chuàng)建私有索引庫分飞,并添加到本地repo中
終端執(zhí)行pod repo add TestSpec https://github.com/rayraychow/TestSpec.git
然后執(zhí)行pod repo
即可查看有沒有添加成功,有TestSpec即是成功
2.創(chuàng)建framework庫
3.本地framework源碼根目錄下睹限,創(chuàng)建.podspec文件
終端執(zhí)行pod spec create TestSDK
生成文件后拖入Xcode工程中譬猫,取消copy勾選
podspec文件修改完后讯檐,把本地私有庫代碼和遠端私有庫關聯(lián),并把代碼都push上去
1).git add .
如果報錯fatal: not a git repository (or any of the parent directories): .git
染服,使用git init
創(chuàng)建git目錄
2).git commit -m '修改的內(nèi)容'
3).git push
4).git tag '0.0.1'
5).git push --tags
注意:每次push后都需要打tag别洪,且tag和.podspec文件中的版本號要一致
如果報錯Ld .../Build/Intermediates.noindex/App.build/Release-iphonesimulator/App.build/Objects-normal/arm64/Binary/App normal arm64
,
在podspec文件中加入:spec.pod_target_xcconfig = { 'VALID_ARCHS' => 'x86_64 armv7 arm64' }
Pod::Spec.new do |spec|
spec.name = "TestSDK"
spec.version = "0.0.1"
spec.summary = "A short description of TestSDK."
spec.description = <<-DESC
這是描述區(qū)柳刮,這里的文字一定要比 spec.summary 中的內(nèi)容長挖垛,
否則spec遠端驗證可能會不通過
DESC
# 這里是主頁地址,可以寫github私有庫的主頁地址
spec.homepage = "https://github.com/rayraychow/TestSDK"
spec.license = "MIT"
spec.author = { "貝勒" => "beile@jravity.com" }
# 這是可以應用的平臺及系統(tǒng)限制
spec.platform = :ios, "12.0"
# 這是私有庫的路徑秉颗,填寫私有庫的git clone 的鏈接就行
spec.source = { :git => "https://github.com/rayraychow/TestSDK.git", :tag => "#{spec.version}" }
# 如果是想暴露源碼痢毒,打開這行
# spec.source_files = "Classes", "Classes/**/*.{h,m}"
# spec.exclude_files = "Classes/Exclude"
# 此處暴露的是framework
spec.vendored_frameworks = "Products/TestSDK.framework"
# 此處聲明swift版本
spec.swift_versions = "5.0"
# 此處聲明支持的類型
spec.pod_target_xcconfig = { 'VALID_ARCHS' => 'x86_64 armv7 arm64' }
# 這是聲明framework依賴的三方庫
spec.dependency "SnapKit"
end
4.校驗podspec文件
1).本地校驗:pod lib lint
2).從本地和遠程驗證:pod spec lint
3).依賴庫(spec.dependency)中 如果包含.a文件,驗證的時候出現(xiàn)錯誤蚕甥。加上這個來讓驗證通過:--use-libraries
4).有警告導致不通過驗證時哪替,加上這個忽略警告:--allow-warnings
5).有錯誤導致不通過驗證時,加上這個查看具體錯誤:--verbose
校驗文件可以直接執(zhí)行pod spec lint --allow-warnings
注意:進行驗證時如果報錯warning: Could not find remote branch 0.1.0 to clone. fatal: Remote branch 0.1.0 not found in upstream origin
說明沒有上傳代碼到倉庫菇怀,先進行代碼上傳凭舶,執(zhí)行 git add . git commit git push ,然后 git tag等流程的上傳爱沟。
5.把.podspec文件push到遠程Spec私有索引庫中
終端執(zhí)行pod repo push TestSpec TestSDK.podspec --allow-warnings --skip-import-validation
如果出現(xiàn)
[!] Found multiple specifications for `SnapKit (0.17.0)`: -/Users/beile/.cocoapods/repos/master/Specs/1/f/6/SnapKit/0.17.0/SnapKit.podspec.json -/Users/beile/.cocoapods/repos/trunk/Specs/1/f/6/SnapKit/0.17.0/SnapKit.podspec.json
時库快,加入命令--sources='https://github.com/CocoaPods/Specs.git'
6.發(fā)布podspec文件到公有庫中
1).注冊cocoaPods
終端執(zhí)行pod trunk register 郵箱地址 '用戶名' --verbose
這里我們一般使用github郵箱和用戶名, 然后在你的郵箱中會收到確認郵件, 在瀏覽器中點擊鏈接確認即注冊成功。
2).驗證cocoaPods
確保打開了郵件中的鏈接之后(正常加載出來就行)钥顽,繼續(xù)執(zhí)行命令
pod trunk me
3).發(fā)布
pod trunk push TestSDK.podspec
該命令的執(zhí)行過程:
a.更新本地 pods庫 ~/.cocoaPods.repo/master
b.驗證*.podspec格式是否正確
c.將 *.podspec 文件轉(zhuǎn)成 JSON 格式
d.對 master 倉庫進行合并义屏、提交
7.使用(和正常的pod庫使用方式一樣)
唯一的區(qū)別是,因為是私有庫蜂大,需要在podfile文件中額外添加源地址
一個是私有的索引庫地址source 'https://github.com/rayraychow/TestSpec.git'
一個是cocoapods的cdn地址source 'https://cdn.cocoapods.org/'