CocoaPods 可以說是 iOS 開發(fā)應(yīng)用最廣泛的包管理工具榛瓮,本篇文章主要介紹 CocoaPods 的第三方庫是怎樣從網(wǎng)絡(luò)集成到我們本地的項目當(dāng)中童谒,也是制作私有庫、開源庫和 iOS 項目組件化的一個知識鋪墊。
讓我們從一張圖片開始:
CocoaPods 工作流程 |
---|
未命名文件
|
遠(yuǎn)程索引庫
遠(yuǎn)程索引庫里存放的是各種框架的描述信息确垫,這個庫托管在 Github 上隔披,地址如下:
https://github.com/CocoaPods/Specs
每個框架下有數(shù)個版本收津,每個版本有一個 json
格式的描述信息裳扯,如下:
{
"name": "CAIStatusBar",
"version": "0.0.1",
"summary": "A simple indicator",
"homepage": "https://github.com/apple5566/CAIStatusBar.git",
"license": "MIT",
"authors": {
"apple5566": "zaijiank110@sohu.com"
},
"platforms": {
"ios": "6.0"
},
"source": {
"git": "https://github.com/apple5566/CAIStatusBar.git",
"tag": "0.0.1"
},
"source_files": "CAIStatusBar/**/*.{h,m}",
"resources": "CAIStatusBar/CAIStatusBar.bundle",
"requires_arc": true
}
其中 git
字段表示該框架的托管地址,也就是上面時序圖中的 遠(yuǎn)程框架庫
噪珊。
本地索引庫
在 install cocoapods
命令后晌缘,需要執(zhí)行 pod setup
這個命令,pod setup
命令就是將遠(yuǎn)程索引庫克隆到本地來痢站,本地索引庫的路徑如下:
~/.cocoapods/repos/master
本地索引庫和遠(yuǎn)程索引庫的目錄一致磷箕,結(jié)構(gòu)如下:
本地索引庫 |
---|
本地索引庫
|
本地索引文件
當(dāng)執(zhí)行 pod search
命令時,如果本地索引文件不存在阵难,會創(chuàng)建這個文件岳枷。
tianziyaodeMacBook-Air:~ Tian$ pod search afn
Creating search index for spec repo 'master'..
如果這個文件存在,則會在此文件中進(jìn)行索引多望,確認(rèn)所需要的框架是否存在嫩舟,本地索引文件的路徑如下:
~/資源庫/Caches/CocoaPods
制作 CocoaPods 庫
上面的流程清楚以后,制作 CocoaPods 庫相信應(yīng)該不會太難了怀偷,大致分為以下幾步:
- 托管框架源碼到 Git家厌;
- 創(chuàng)建框架描述信息;
- 上傳框架描述信息到
https://github.com/CocoaPods/Specs
椎工; - 命令行
pod setup
饭于, 創(chuàng)建本地索引庫; - 命令行
pod install
维蒙,將框架集成到項目中掰吕;
現(xiàn)在開始動手吧!首先在桌面新建一個 testLib
目錄颅痊,在該目錄下新建一個 Classes
目錄殖熟,用來存放框架源碼,然后將 testLib
托管到 Git斑响。
你可以給 Classes 目錄任意的命名菱属,Classes 只是一種約定俗稱的命名钳榨。
pod spec
pod spec
命令用于創(chuàng)建框架的描述信息文件,文檔如下:
https://guides.cocoapods.org/syntax/podspec.html
現(xiàn)在在 testLib
目錄下執(zhí)行:
pod spec create testLib
目錄下會創(chuàng)建一個 testLib.podspec
文件纽门,然后編輯這個文件薛耻,主要有以下幾個字段:
- version:這個 spec 映射的版本,保證 Git 的
releases
與此對應(yīng)赏陵; - homepage:項目主頁饼齿;
- source:框架源代碼的托管地址;
- tag:與 version 對應(yīng)蝙搔;
- source_files:框架源代碼的目錄缕溉、文件、文件類型等規(guī)則杂瘸;
CocoaPods 公開庫
根據(jù)上面的步驟倒淫,現(xiàn)在你需要將生成的 testLib.podspec
文件上傳到遠(yuǎn)程索引庫伙菊,在此之前败玉,你需要注冊一個 Trunk 賬號,文檔如下:
https://guides.cocoapods.org/making/getting-setup-with-trunk.html
現(xiàn)在執(zhí)行下面的命令镜硕,記得修改郵箱昵稱描述等:
pod trunk register ziyao.tian@gmail.com 'Tian' --description='macbook air'
你的郵箱會收到一封郵件运翼,打開郵件里面的鏈接,會有類似 you can back termainal
的提示兴枯,現(xiàn)在回到終端血淌。
pod lib lint
檢查 testLib.podspec
的合法性,根據(jù)錯誤提示修復(fù)問題财剖,當(dāng)顯示 passed validation
后悠夯,執(zhí)行下面的命令:
pod trunk push testLib.podspec
提示信息如下:
Updating spec repo `master`
--------------------------------------------------------------------------------
?? Congrats
?? testLib (0.0.7) successfully published
?? October 17th, 00:38
?? https://cocoapods.org/pods/testLib
?? Tell your friends!
--------------------------------------------------------------------------------
此時你的 testLib.podspec
就會 pull request
到遠(yuǎn)程索引庫,CocoaPods 官方審核通過后躺坟,就可以出現(xiàn)在遠(yuǎn)程索引庫中沦补,當(dāng)遠(yuǎn)程索引庫收錄后:
pod setup
這時你的本地索引庫,會新加入 testLib.podspec
這條記錄咪橙,但是本地索引文件還未更新夕膀,因此刪除掉以下路徑的本地索引文件:
~/資源庫/Caches/CocoaPods/search_index.json
執(zhí)行 pod search testLib
命令,當(dāng) search_index.json
文件重建完畢后美侦,就可以在使用這個遠(yuǎn)程框架庫了产舞。
CocoaPods 私有庫
有了公開庫,當(dāng)然也就有私有庫菠剩,私有庫主要分為遠(yuǎn)程和本地兩種易猫,什么時候會用到私用庫呢?也就是需要將源碼封裝成庫具壮,但又不希望將源碼公開准颓,一般的使用場景是公司內(nèi)部的組件化開發(fā)违霞。
本地私有庫
本地私有庫就是創(chuàng)建一個倉庫,將其存儲在本地瞬场,在本地的其他工程中直接使用买鸽。首先在桌面新建一個庫,路徑如下:
LocalLib/NetWork/Classes/Test.swift
接著創(chuàng)建一個殼工程贯被,現(xiàn)在你的目標(biāo)是使用 pod
的方式眼五,將 NetWork
這個庫集成到殼工程中。
創(chuàng)建本地 GIt 倉庫
將 NetWork
加入到 Git彤灶,命令如下:
git init
git add.
git commit -m 'x'
創(chuàng)建庫描述文件
和公開庫一樣看幼,我們需要先創(chuàng)建一個 spec
文件,命令如下:
pod spec create LocalLib
編輯 NetWork.podspec
文件幌陕,修改成下面這樣:
Pod::Spec.new do |s|
s.name = "NetWork"
s.version = "0.0.1"
s.summary = "A short description of NetWork."
s.description = "A short description of NetWork.xxxxxxxxxxxxxxxxxx"
s.homepage = "http://EXAMPLE/NetWork"
s.license = "MIT"
s.author = { "tianziyao" => "ziyao.tian@gmail.com" }
s.source = { :git => "", :tag => "#{s.version}" }
s.source_files = "Classes", "Classes/**/*.{h,m,swift}"
end
現(xiàn)在你的本地庫已經(jīng)準(zhǔn)備完畢了诵姜,下面就可以使用這個庫了。
導(dǎo)入本地私有庫
現(xiàn)在進(jìn)入到殼工程目錄下搏熄,執(zhí)行命令:
pod init
編輯 Podfile
文件棚唆,如下:
target 'Test' do
use_frameworks!
pod 'NetWork', :path => '../NetWork'
target 'TestTests' do
inherit! :search_paths
end
target 'TestUITests' do
inherit! :search_paths
end
end
這里有一個 path
關(guān)鍵字,它表示在 pod install
執(zhí)行時心例,在指定的路徑下尋找 NetWork.podspec
文件宵凌。
下面執(zhí)行 pod install
命令,提示信息如下:
Analyzing dependencies
Fetching podspec for `NetWork` from `../NetWork`
Downloading dependencies
Installing NetWork (0.0.1)
Generating Pods project
Integrating client project
現(xiàn)在 NetWork
這個庫就集成到了殼工程中止后。
與使用遠(yuǎn)程庫不同瞎惫,本地庫的源文件會在 Development Pods
這個目錄下,而不是 Pods
目錄译株,順便一提瓜喇,CocoaPods 的庫開發(fā),一般也是這樣搭建環(huán)境的歉糜,開發(fā)完成后再修改 spec
文件乘寒,將其 pull request
到遠(yuǎn)程索引庫。
CocoaPods 模板庫
本地私有庫這個方式還存在以下問題:
- 需要手動創(chuàng)建
podspec
文件现恼; - 無法單獨測試肃续,需要依托于殼工程運行;
假設(shè)我們有一個基礎(chǔ)組件叉袍,里面全部是擴(kuò)展文件始锚,無法單獨運行,如果依托殼工程運行喳逛,只有這一個組件瞧捌,那么這個殼工程實際跟測試工程是一樣的,但殼工程內(nèi)有多個組件呢?
我們在殼工程中進(jìn)行測試的話姐呐,不但要對其他的組件進(jìn)行編譯殿怜,而且自己負(fù)責(zé)的組件也可能會收到其他組件的影響,這樣也就失去了組件化開發(fā)的本意曙砂,那么怎么優(yōu)化呢头谜?
單獨測試
首先在 LocalLib/NetWork/
路徑下創(chuàng)建一個測試工程 Example
,然后將 Classes
拖到這個測試工程中鸠澈,這里需要注意的是柱告,Example
和 Classes
是引用關(guān)系,不要 Copy笑陈。
簡單粗暴的拖拽际度,現(xiàn)在 Example
工程就可以使用 NetWork
庫了。
另外一種方式是將 NetWork
通過 CocoaPods 安裝在 Example
中涵妥,和安裝在殼工程一樣乖菱。
看到這里,是不是感覺很煩蓬网?就是想做個測試而已窒所,還要拖來拖去,那么繁瑣拳缠。
不要著急下面來介紹一種更快捷高效的方式墩新,執(zhí)行下面的命令:
pod lib create BaseMoudle
////////////////////////////////////////////////////////////////////////
What language do you want to use?? [ Swift / ObjC ]
> Swift
Would you like to include a demo application with your library? [ Yes / No ]
> Yes
Which testing frameworks will you use? [ Quick / None ]
> None
Would you like to do view based testing? [ Yes / No ]
> Yes
現(xiàn)在我們就有了一個 CocoaPods 的模板工程贸弥,它的結(jié)構(gòu)是這樣的:
.
├── BaseMoudle
│ ├── Assets
│ └── Classes
│ └── ReplaceMe.swift
├── BaseMoudle.podspec
├── Example
│ ├── BaseMoudle
│ ├── BaseMoudle.xcodeproj
│ ├── BaseMoudle.xcworkspace
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Pods
├── LICENSE
├── README.md
└── _Pods.xcodeproj -> Example/Pods/Pods.xcodeproj
看吧窟坐,把源碼拖到 ReplaceMe.swift
的同級目錄,執(zhí)行 pod install
绵疲,就完成了本地私有庫和其測試工程哲鸳。
這一步可能會有 Swift 語言版本的問題,保持測試工程和私有庫源碼語言版本一致就可以盔憨。
遠(yuǎn)程私有庫
遠(yuǎn)程私有庫工作流程 |
---|
遠(yuǎn)程私有庫
|
現(xiàn)在使用 pod lib create
就可以方便的生成一個本地私有庫了徙菠,但是本地私有庫有一定的局限性,例如:
- 需要在
Podfile
文件中主動指明路徑郁岩; - 版本升級不容易維護(hù)婿奔;
- 多人開發(fā)時,不方便進(jìn)行合作问慎;
遠(yuǎn)程私有庫就可以方便的解決以上的問題萍摊,制作遠(yuǎn)程私有庫分為以下幾個步驟:
- 創(chuàng)建私有 Git 遠(yuǎn)程倉庫;
- 創(chuàng)建私有 CocoaPods 遠(yuǎn)程索引庫如叼;
- 創(chuàng)建 Pod 所需要的項目工程文件冰木,并上傳到 Git 遠(yuǎn)程私有庫;
- 驗證
podspec
描述文件; - 向私有 CocoaPods 遠(yuǎn)程索引庫提交
podspec
描述文件踊沸; - 使用 Pod 庫歇终;
Git 倉庫的創(chuàng)建在此就不在贅述了,本文中我使用碼市做示例逼龟,私有 CocoaPods 遠(yuǎn)程索引庫實際上也是一個 Git 倉庫评凝,現(xiàn)在我們有兩個私有庫,一個用來存放 Pod 庫的源碼腺律,一個用來存放 Pod 庫的描述文件肥哎。
SSH 授權(quán)
添加私有索引庫需要使用 SSH 授權(quán),也是和 Git 倉庫一樣的疾渣,了解的同學(xué)可以跳過這一步驟篡诽,首先創(chuàng)建公鑰:
ssh-keygen
然后找到下面的文件:
~/.ssh/id_rsa.pub
里面存放的字符就是公鑰了,然后將公鑰添加碼市榴捡,鏈接如下:
https://coding.net/user/account/setting/keys
添加私有遠(yuǎn)程索引庫
現(xiàn)在執(zhí)行 pod repo
杈女,可以看到下面的信息:
master
- Type: git (master)
- URL: https://github.com/CocoaPods/Specs.git
- Path: /Users/Tian/.cocoapods/repos/master
現(xiàn)在我們只有一個 CocoaPods 遠(yuǎn)程索引庫,也是官方的索引庫吊圾,下面執(zhí)行:
pod repo add TZYSpecs git@git.coding.net:tianziyao/TZYSpecs.git
此時我們的 CocoaPods 遠(yuǎn)程索引庫就安裝好了达椰,到下面的路徑去看一下:
~/.cocoapods/repos
上傳源碼到 Git
還記得 pod lib create
命令嗎?前面我們使用它來制作了本地私有庫项乒,現(xiàn)在它又排上用場了啰劲,執(zhí)行:
pod lib create BaseComponent
源碼拖到 ReplaceMe.swift
的同級目錄,它現(xiàn)在看起來應(yīng)該是這個樣子:
.
├── BaseComponent
│ ├── Assets
│ └── Classes
│ ├── Extension
│ │ ├── Array+Safe.swift
│ │ ├── CALayer+PauseAimate.swift
│ │ ├── UIImage+.swift
│ │ └── UIView+Property.swift
├── BaseComponent.podspec
├── Example
├── LICENSE
├── README.md
└── _Pods.xcodeproj -> Example/Pods/Pods.xcodeproj
執(zhí)行 pod install
檀何,就完成了本地私有庫和其測試工程蝇裤,通過測試之后,我們就可以把這個本地私有庫制作成遠(yuǎn)程私有庫了频鉴。
首先修改 BaseComponent.podspec
文件:
Pod::Spec.new do |s|
s.name = 'BaseComponent'
s.version = '0.1.0'
s.summary = '基礎(chǔ)組價'
s.description = '包括基本配置栓辜,常量,擴(kuò)展垛孔,工具類等'
s.homepage = 'https://coding.net/u/tianziyao/p/BaseComponent'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'tianziyao' => 'ziyao.tian@gmail.com' }
s.source = { :git => 'https://git.coding.net/tianziyao/BaseComponent.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.source_files = 'BaseComponent/Classes/**/*'
end
然后使用質(zhì)量檢查工具驗證一下藕甩,保證在 BaseComponent.podspec
路徑下,執(zhí)行:
pod lib lint
如果你使用 Swift周荐,會得到一個提示:
-> BaseComponent (0.1.0)
- WARN | [iOS] swift_version: The validator for Swift projects uses Swift 3.0 by default, if you are using a different version of swift you can use a `.swift-version` file to set the version for your Pod. For example to use Swift 2.3, run:
`echo "2.3" > .swift-version`
[!] BaseComponent did not pass validation, due to 1 warning (but you can use `--allow-warnings` to ignore it).
You can use the `--no-clean` option to inspect any issue.
根據(jù)提示修復(fù)就好了狭莱,在這里你可能會遇到很多 Swift 語言版本的問題,善用搜索引擎吧概作,通過檢驗以后提示如下:
-> BaseComponent (0.1.0)
BaseComponent passed validation.
下面執(zhí)行:
git add .
git commit -m 'x'
然后和遠(yuǎn)程倉庫進(jìn)行關(guān)聯(lián):
git remote add origin https://git.coding.net/tianziyao/BaseComponent.git
git pull origin master
git push origin master
上傳 Spec 到遠(yuǎn)程索引庫
首先執(zhí)行下面的命令:
pod spec lint
提示如下:
-> BaseComponent (0.1.0)
- ERROR | [iOS] unknown: Encountered an unknown error ([!] /usr/local/bin/git clone https://git.coding.net/tianziyao/BaseComponent.git /var/folders/2v/qkx5m4sx4dg86x4c82yfyjdc0000gn/T/d20171021-69604-1bekfgk --template= --single-branch --depth 1 --branch 0.1.0
Cloning into '/var/folders/2v/qkx5m4sx4dg86x4c82yfyjdc0000gn/T/d20171021-69604-1bekfgk'...
warning: Could not find remote branch 0.1.0 to clone.
fatal: Remote branch 0.1.0 not found in upstream origin
) during validation.
Analyzed 1 podspec.
[!] The spec did not pass validation, due to 1 error.
根據(jù)提示腋妙,我們需要先建立一個 Tag:
git tag '0.1.0'
git push --tags
pod spec lint
檢驗通過后,提示如下:
-> BaseComponent (0.1.0)
Analyzed 1 podspec.
BaseComponent.podspec passed validation.
然后將 podspec
文件推到遠(yuǎn)程私有索引庫:
pod repo push TZYSpecs BaseComponent.podspec
現(xiàn)在看一下本地索引庫中是否已經(jīng)添加成功:
~/.cocoapods/repos
再看一看你的遠(yuǎn)程索引庫中是否添加成功仆嗦,現(xiàn)在搜索一下本地索引文件試試:
-> BaseComponent (0.1.0)
基礎(chǔ)組價
pod 'BaseComponent', '~> 0.1.0'
- Homepage: https://coding.net/u/tianziyao/p/BaseComponent
- Source: https://git.coding.net/tianziyao/BaseComponent.git
- Versions: 0.1.0 [TZYSpecs repo]
現(xiàn)在我們可以找到自己的遠(yuǎn)程私有庫了辉阶,下面將 Podfile
文件改成這樣:
project 'Ting.xcodeproj'
source 'https://github.com/CocoaPods/Specs.git'
source 'git@git.coding.net:tianziyao/TZYSpecs.git'
target 'Ting' do
use_frameworks!
pod 'BaseComponent'
pod 'Alamofire'
target 'TingTests' do
inherit! :search_paths
end
target 'TingUITests' do
inherit! :search_paths
end
end
執(zhí)行 pod install
,整個遠(yuǎn)程私有庫的搭建和使用就完成了。
CocoaPods 庫升級
我們使用遠(yuǎn)程私有庫的目的就是為了版本升級和多人開發(fā)谆甜,那么遠(yuǎn)程私有庫如何進(jìn)行升級垃僚,升級后其他人又如何使用呢?現(xiàn)在我們給 BaseComponent
進(jìn)行升級规辱,給它再增加一些功能:
.
├── BaseComponent
│ ├── Assets
│ └── Classes
│ ├── Const
│ │ └── Const.swift
│ ├── Extension
│ │ ├── Array+Safe.swift
│ │ ├── CALayer+PauseAimate.swift
│ │ ├── UIImage+.swift
│ │ └── UIView+Property.swift
│ └── Tool
│ ├── AlertTool.swift
│ ├── CacheTool.swift
│ ├── DeviceMessage.swift
│ └── NoticeLocalTool.swift
├── BaseComponent.podspec
├── Example
├── LICENSE
├── README.md
└── _Pods.xcodeproj -> Example/Pods/Pods.xcodeproj
在 BaseComponent
的測試工程中測試無誤后谆棺,將 BaseComponent.podspec
的 version
修改一下:
Pod::Spec.new do |s|
s.name = 'BaseComponent'
s.version = '0.2.0'
s.summary = '基礎(chǔ)組價'
s.description = '包括基本配置,常量罕袋,擴(kuò)展改淑,工具類等'
s.homepage = 'https://coding.net/u/tianziyao/p/BaseComponent'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'tianziyao' => 'ziyao.tian@gmail.com' }
s.source = { :git => 'https://git.coding.net/tianziyao/BaseComponent.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.source_files = 'BaseComponent/Classes/**/*'
end
現(xiàn)在檢查一下私有庫是否有錯誤:
pod lib lint
檢查通過后就可以將 BaseComponent
的 0.2.0
版本推到遠(yuǎn)程私有庫中,同時建立 0.2.0
的 Tag浴讯。
然后檢查一下 spec
文件:
pod spec lint
檢查通過后朵夏,執(zhí)行:
pod repo push TZYSpecs BaseComponent.podspec
遠(yuǎn)程私有庫和遠(yuǎn)程私有索引庫全部更新完畢,現(xiàn)在我們回到使用者的視角榆纽,這個庫可以使用了嗎仰猖?還不行。
因為本地的索引文件還沒有更新奈籽,這個源還找不到饥侵,現(xiàn)在進(jìn)入殼工程,執(zhí)行:
pod update --no-repo-update
pod install
BaseComponent
的 0.2.0
版本就乖乖的進(jìn)入了殼工程衣屏。
CocoaPods 庫依賴
在上面的殼工程中躏升,我們引入了 Alamofire
這個框架,但是如果用著用著突然覺得不爽了狼忱,要換框架膨疏,這時 Alamofire
的引用在工程中已經(jīng)無處不再了,這樣換的話是不是很痛苦藕赞?
所以我們一般在開發(fā)中都會封裝網(wǎng)絡(luò)請求成肘,做到分層解耦,這樣如果換框架斧蜕,只修改網(wǎng)絡(luò)請求這層的封裝就可以了,那么現(xiàn)在我們需要將 Alamofire
封裝成 Network
砚偶,再把 Network
弄到我們的 BaseComponent
里面去批销,怎么做呢?
現(xiàn)在先將 Network
拖到 BaseComponent
的 Classes
目錄中染坯,因為 BaseComponent
的測試工程沒有 Alamofire
均芽,所以 Network
肯定是會報錯了,不要慌单鹿,下面我們修改 spec
文件:
Pod::Spec.new do |s|
s.name = 'BaseComponent'
s.version = '0.2.0'
s.summary = '基礎(chǔ)組價'
s.description = '包括基本配置掀宋,常量,擴(kuò)展,工具類等'
s.homepage = 'https://coding.net/u/tianziyao/p/BaseComponent'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'tianziyao' => 'ziyao.tian@gmail.com' }
s.source = { :git => 'https://git.coding.net/tianziyao/BaseComponent.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
s.source_files = 'BaseComponent/Classes/**/*'
s.dependency 'Alamofire'
s.dependency 'SDWebImage'
end
dependency
指明了這個庫的依賴劲妙,改好之后 pod install
湃鹊,Alamofire
就安裝到了 BaseComponent
的測試工程中,現(xiàn)在就可以使用 Alamofire
進(jìn)行網(wǎng)絡(luò)請求封裝镣奋,直接 import
就可以了:
import Foundation
import Alamofire
import SDWebImage
open class Network {
open class func request(url: String, parameters: [String:Any]?) {
Alamofire.request(url, method: .get, parameters: parameters).responseJSON { (response) in
guard let JSON = response.result.value else { return }
print(JSON)
}
}
}
extension UIImageView {
public func image(with url: URL?) {
self.sd_setImage(with: url)
}
}
現(xiàn)在再進(jìn)行一次遠(yuǎn)程私有庫升級币呵,整個依賴就做好了,需要注意的是侨颈,已經(jīng)做了依賴的話余赢,相關(guān)的庫就可以從 Podfile
文件中去掉了:
project 'Ting.xcodeproj'
source 'https://github.com/CocoaPods/Specs.git'
source 'git@git.coding.net:tianziyao/TZYSpecs.git'
target 'Ting' do
use_frameworks!
pod 'BaseComponent'
# pod 'Alamofire'
target 'TingTests' do
inherit! :search_paths
end
target 'TingUITests' do
inherit! :search_paths
end
end
現(xiàn)在是我們依賴的是公開庫,直接升級 CocoaPods 私有庫就可以哈垢,但是如果依賴的是另外一個私有庫妻柒,這個依賴關(guān)系最終還要上傳到私有索引庫中,這樣其他人在使用的時候才會知道這個依賴關(guān)系耘分,現(xiàn)在走一下升級的流程蛤奢,你會得到類似這個報錯:
[!] The `TargetComponent.podspec` specification does not validate.
這個報錯是因為 TargetComponent
這個庫沒有在官方的索引庫當(dāng)中,忽略就可以了陶贼,當(dāng)然啤贩,在使用的時候,TargetComponent
這個庫可以在你的本地索引文件中找到拜秧,否則無法使用痹屹。
CocoaPods 資源依賴
現(xiàn)在我們可以讓一個庫依賴另外一個庫,但是看下面這段代碼:
/// 獲取中間的視圖
open class func tabBarMiddleView() -> TZYTabBarMiddleView {
let view = Bundle.main.loadNibNamed("TZYTabBarMiddleView", owner: nil, options: nil)?.first
return (view as? TZYTabBarMiddleView) ?? TZYTabBarMiddleView()
}
這段代碼讀取了一個 XIB 文件枉氮,這個庫的結(jié)構(gòu)是這樣的:
.
├── Assets
└── Classes
└── MainModule
├── Controller
│ ├── TZYNavBarC.swift
│ └── TZYTabBarC.swift
└── View
├── TZYNavBar.swift
├── TZYTabBar.swift
├── TZYTabBarMiddleView.swift
└── TZYTabBarMiddleView.xib
我們可以成功調(diào)用這個方法嗎志衍?不能,因為 TZYTabBarMiddleView.xib
這個文件的 Target 是 MainModule
聊替,使用 CocoaPods 把這個庫安裝到我們項目后楼肪,XIB 文件即使在,也是在 Pods 這個工程里惹悄,而我們在殼工程中使用 TZYTabBarMiddleView.xib
春叫,也是必然找不到的。
下面我們把模板庫的測試工程編譯一下泣港,打開 Products 目錄下的 .app
文件暂殖,看一下文件結(jié)構(gòu):
.
├── Base.lproj
│ ├── LaunchScreen.nib
│ └── Main.storyboardc
├── Frameworks
│ ├── Alamofire.framework
│ │ ├── Alamofire
│ │ ├── Info.plist
│ │ └── _CodeSignature
│ │ └── CodeResources
│ ├── BaseComponent.framework
│ │ ├── BaseComponent
│ │ ├── Info.plist
│ │ └── _CodeSignature
│ │ └── CodeResources
│ ├── SDWebImage.framework
│ │ ├── Info.plist
│ │ ├── SDWebImage
│ │ └── _CodeSignature
│ │ └── CodeResources
│ ├── TargetComponent.framework
│ │ ├── Info.plist
│ │ ├── TZYTabBarMiddleView.nib
│ │ ├── TargetComponent
│ │ └── _CodeSignature
│ │ └── CodeResources
├── Info.plist
├── PkgInfo
├── TargetComponent_Example
├── _CodeSignature
│ └── CodeResources
└── libswiftRemoteMirror.dylib
通過路徑可以看到,TZYTabBarMiddleView.nib
是在:
mainBundle/Frameworks/TargetComponent.framework
這個路徑下面当纱,因此 mainBundle.loadXIb
肯定是找不到資源文件的呛每,那么該如何修改呢?
open class func tabBarMiddleView() -> TZYTabBarMiddleView {
let view = Bundle(for: TZYTabBarMiddleView.self).loadNibNamed("TZYTabBarMiddleView", owner: nil, options: nil)?.first
//let view = Bundle.main.loadNibNamed("TZYTabBarMiddleView", owner: nil, options: nil)?.first
return (view as? TZYTabBarMiddleView) ?? TZYTabBarMiddleView()
}
這部分的重點就是 Bundle(for aClass: Swift.AnyClass)
這個方法坡氯。
CocoaPods 圖片依賴
上面我們講到了怎樣使用 Pod 庫里面的 XIB 文件晨横,但是還有其他資源文件洋腮,例如圖片、音頻手形、視頻啥供,圖片我們一般是放在 Assets.xcassets
,但是 Pod 庫并沒有對應(yīng)的路徑叁幢,那么它所需要的圖片放在哪里滤灯,已經(jīng)如何使用呢?現(xiàn)在使用 pod lib create
命令創(chuàng)建一個 Pod 庫曼玩,進(jìn)入以下路徑:
組件名/Assets
把一些圖片拖入到 Assets
文件夾內(nèi)鳞骤,然后在 podspec
文件中加入以下代碼:
s.resource_bundles = {
'組件名' => ['組件名/Assets/*.png'] //只加載 png 文件
# '組件名' => ['組件名/Assets/*'] //加載所有文件
}
然后執(zhí)行 pod install
,Pod 庫中就出現(xiàn)了之前拖入 Assets
文件夾的圖片黍判,但是現(xiàn)在還不能使用豫尽,我們先來看一下打包以后這些圖片的路徑:
.
├── Base.lproj
│ ├── LaunchScreen.nib
│ └── Main.storyboardc
│ ├── Info.plist
│ ├── UIViewController-vXZ-lx-hvc.nib
│ └── vXZ-lx-hvc-view-kh9-bI-dsS.nib
├── Frameworks
│ ├── TargetComponent.framework
│ │ ├── Info.plist
│ │ ├── TZYTabBarMiddleView.nib
│ │ ├── TargetComponent
│ │ ├── TargetComponent.bundle
│ │ │ ├── Info.plist
│ │ │ ├── tabbar_bg_320x49_@3x.png
│ │ │ └── zxy_icon_48x48_@2x.png
│ │ └── _CodeSignature
│ │ └── CodeResources
│ └── libswiftUIKit.dylib
├── Info.plist
├── PkgInfo
├── TargetComponent_Example
├── _CodeSignature
│ └── CodeResources
├── embedded.mobileprovision
└── libswiftRemoteMirror.dylib
可以看到,打包后的路徑在:
mainBundle/Frameworks/TargetComponent.framework/TargetComponent.bundle
這個路徑下面顷帖,而代碼中的 UIImage(named: "tabbar_bg")
讀取的是 mainBundle
下的資源文件美旧,因此還是找不到的,那么這時使用圖片贬墩,應(yīng)該將代碼改成這樣:
backgroundImage = UIImage.image(withName: "tabbar_bg_320x49_@3x.png")
extension UIImage {
public class func image(withName name: String) -> UIImage? {
let bundle = Bundle(for: UIImage.self)
guard let path = bundle.path(forResource: name, ofType: nil, inDirectory: "TargetComponent.bundle") else {
return nil
}
return UIImage(contentsOfFile: path)
}
}
這里需要注意的是榴嗅,文件名需要完整。以上是在代碼中加載圖片陶舞,如果是在 XIB 中加載圖片嗽测,應(yīng)該怎樣做呢?那么再看一下上面的目錄結(jié)構(gòu)肿孵,TZYTabBarMiddleView.nib
和 TargetComponent.bundle
處于同一個目錄唠粥,我們可以在 TZYTabBarMiddleView.xib
中通過相對路徑,使用 TargetComponent.bundle
里面的圖片停做,因此在 XIB 中晤愧,圖片名應(yīng)該是這樣的:
TargetComponent.bundle/tabbar_bg_320x49_@3x
CocoaPods 子庫
現(xiàn)在我們實現(xiàn)了一個完整的遠(yuǎn)程私有庫,可以升級蛉腌,依賴其他的庫官份,提供給其他人使用,但是現(xiàn)在還有一點問題眉抬,其他人如果要用我們的庫贯吓,就需要把 BaseComponent
完整的克隆過來,但是他可能只需要 BaseComponent
里面的 Network
蜀变,其他的擴(kuò)展、工具等并不想使用介评,也不想導(dǎo)入過來库北,怎么辦爬舰?有兩種方案:
- 把
Network
剝離出來,再單獨建一個遠(yuǎn)程私有庫寒瓦; - 使用子庫遷出
Network
情屹;
第一種方案大家已經(jīng)知道了,就是上面的一大篇杂腰,麻煩不說垃你,而且東西一多起來,這里一個庫喂很,那里一個庫惜颇,也不容易管理,所以少辣,下面就有請子庫隆重登場凌摄。
在開始之前,我們先來開一個東西漓帅,下面是 pod search AFN
中的一條記錄:
-> AFNetworking (3.1.0)
A delightful iOS and OS X networking framework.
pod 'AFNetworking', '~> 3.1.0'
- Homepage: https://github.com/AFNetworking/AFNetworking
- Source: https://github.com/AFNetworking/AFNetworking.git
- Versions: 3.1.0, 3.0.4, 3.0.3, 3.0.2, 3.0.1, 3.0.0, 3.0.0-beta.3, 3.0.0-beta.2, 3.0.0-beta.1, 2.6.3, 2.6.2, 2.6.1, 2.6.0, 2.5.4, 2.5.3, 2.5.2, 2.5.1, 2.5.0, 2.4.1,
2.4.0, 2.3.1, 2.3.0, 2.2.4, 2.2.3, 2.2.2, 2.2.1, 2.2.0, 2.1.0, 2.0.3, 2.0.2, 2.0.1, 2.0.0, 2.0.0-RC3, 2.0.0-RC2, 2.0.0-RC1, 1.3.4, 1.3.3, 1.3.2, 1.3.1, 1.3.0, 1.2.1,
1.2.0, 1.1.0, 1.0.1, 1.0, 1.0RC3, 1.0RC2, 1.0RC1, 0.10.1, 0.10.0, 0.9.2, 0.9.1, 0.9.0, 0.7.0, 0.5.1 [master repo]
- Subspecs:
- AFNetworking/Serialization (3.1.0)
- AFNetworking/Security (3.1.0)
- AFNetworking/Reachability (3.1.0)
- AFNetworking/NSURLSession (3.1.0)
- AFNetworking/UIKit (3.1.0)
注意 Subspecs
這里锨亏,它就是本節(jié)要講的東西,首先將 spec
改成下面這樣:
Pod::Spec.new do |s|
s.name = 'BaseComponent'
s.version = '0.4.0'
s.summary = '基礎(chǔ)組價'
s.description = '包括基本配置忙干,常量器予,擴(kuò)展,工具類等'
s.homepage = 'https://coding.net/u/tianziyao/p/BaseComponent'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'tianziyao' => 'ziyao.tian@gmail.com' }
s.source = { :git => 'https://git.coding.net/tianziyao/BaseComponent.git', :tag => s.version.to_s }
s.ios.deployment_target = '8.0'
# s.source_files = 'BaseComponent/Classes/**/*'
s.subspec 'Network' do |n|
n.source_files = 'BaseComponent/Classes/Network/**/*'
n.dependency 'Alamofire'
n.dependency 'SDWebImage'
end
s.subspec 'Const' do |c|
c.source_files = 'BaseComponent/Classes/Const/**/*'
end
s.subspec 'Extension' do |e|
e.source_files = 'BaseComponent/Classes/Extension/**/*'
end
s.subspec 'Tool' do |t|
t.source_files = 'BaseComponent/Classes/Tool/**/*'
end
end
在這里要注意 source_files
和 dependency
以及版本的變化捐迫,修改完成推到遠(yuǎn)程索引庫乾翔,并打好 0.4.0
的分支,執(zhí)行:
pod spec lint
pod repo push TZYSpecs BaseComponent.podspec
pod update --no-repo-update
pod search Base
現(xiàn)在就可以找到了:
-> BaseComponent (0.4.0)
基礎(chǔ)組價
pod 'BaseComponent', '~> 0.4.0'
- Homepage: https://coding.net/u/tianziyao/p/BaseComponent
- Source: https://git.coding.net/tianziyao/BaseComponent.git
- Versions: 0.4.0, 0.3.0, 0.2.0, 0.1.0 [TZYSpecs repo]
- Subspecs:
- BaseComponent/Network (0.4.0)
- BaseComponent/Const (0.4.0)
- BaseComponent/Extension (0.4.0)
- BaseComponent/Tool (0.4.0)
那么如何使用呢弓乙?把 Podfile
改成這樣:
project 'Ting.xcodeproj'
source 'https://github.com/CocoaPods/Specs.git'
source 'git@git.coding.net:tianziyao/TZYSpecs.git'
target 'Ting' do
use_frameworks!
pod 'BaseComponent/Network'
# 也可以用下面的寫法
# pod 'BaseComponent', :subspecs => ['Network', 'Extension']
target 'TingTests' do
inherit! :search_paths
end
target 'TingUITests' do
inherit! :search_paths
end
end
現(xiàn)在 pod install
末融,就完成了子庫的創(chuàng)建和使用。
結(jié)尾
這篇文章斷斷續(xù)續(xù)寫了快一周暇韧,其實一般我們用不到 CocoaPods 這些功能勾习,不過了解一下 CocoaPods 的工作原理也是沒有壞處的。
這篇文章主要是為了使用 CocoaPods 進(jìn)行組件化開發(fā)懈玻,關(guān)于組件化開發(fā)的思想巧婶,可以看下面這篇文章: