本地私有庫和遠端私有庫的使用
- 一 本地私有庫
-
- 1.1 建立本地 git倉庫
- 1.2 建立庫描述檔案
- 1.3 導入本地私有庫
- 二 本地私有庫 - 單獨測試
-
- 方案一
- 方案二
- 方案三(推薦)
- 三 遠端私有庫
-
- SSH 授權
- 添加私有遠端索引庫
- 上傳源碼到 Git
- 上傳 Spec 到遠端索引庫
- CocoaPods 庫更新
- CocoaPods 庫依賴
- CocoaPods 子庫
- CocoaPods 資源依賴
- CocoaPods 圖檔依賴
一 本地私有庫
本地私有庫就是建立一個倉庫,将其存儲在本地,在本地的其他工程中直接使用。首先在桌面建立一個庫,路徑如下:
BaseTool/Classes/Network.h
BaseTool/Classes/Network.m
接着建立一個殼工程,現在你的目标是使用 pod 的方式,将 NetWork 這個庫內建到殼工程中。
1.1 建立本地 git倉庫
git init
git add.
git commit -m 'x'
1.2 建立庫描述檔案
和公開庫一樣,我們需要先建立一個 spec 檔案,指令如下:
- 編輯 Network.podspec 檔案
Pod::Spec.new do |s|
s.name = "Network"
s.version = "0.0.1"
s.summary = "Network."
s.homepage = ""
s.license = 'MIT'
s.author = { "goodswifter" => "[email protected]" }
s.source = { :git => "", :tag => "#{s.version}" }
s.source_files = "Classes/**/*.{h,m}"
s.platform = :ios, "9.0" #平台及支援的最低版本
end
現在你的本地庫已經準備完畢了,下面就可以使用這個庫了。
1.3 導入本地私有庫
現在進入到殼工程目錄下,執行指令:
pod init
編輯
Podfile
檔案,如下:
platform :ios, '9.0'
target 'TestLocalPod' do
use_frameworks!
pod 'Network', :path => '../Network'
end
這裡有一個
path
關鍵字,它表示在
pod install
執行時,在指定的路徑下尋找
Network.podspec
檔案。
下面執行 pod install 指令,提示資訊如下:
Analyzing dependencies
Downloading dependencies
Installing Network (0.0.1)
Generating Pods project
Integrating client project
Pod installation complete! There is 1 dependency from the Podfile and 1 total pod installed.
現在
Network
這個庫就內建到了殼工程中。
與使用遠端庫不同,本地庫的源檔案會在
Development Pods
這個目錄下,而不是
Pods
目錄,順便一提,
CocoaPods
的庫開發,一般也是這樣搭建環境的,開發完成後再修改
spec
檔案,将其
pull request
到遠端索引庫。
二 本地私有庫 - 單獨測試
方案一
首先在
LocalLib/Network/
路徑下建立一個測試工程
Example
,然後将
Classes
拖到這個測試工程中,這裡需要注意的是,
Example
和
Classes
是引用關系,不要
Copy
。
簡單粗暴的拖拽,現在
Example
工程就可以使用
Network
庫了。
方案二
将
Network
通過
CocoaPods
安裝在
Example
中,和安裝在殼工程一樣。
方案三(推薦)
看到這裡,是不是感覺很煩?就是想做個測試而已,還要拖來拖去,那麼繁瑣。
不要着急下面來介紹一種更快捷高效的方式,執行下面的指令:
pod lib create ADFMBase
----------------------------
What platform do you want to use?? [ iOS / macOS ] # 平台
> ios
What language do you want to use?? [ Swift / ObjC ] # 語言
> objc
Would you like to include a demo application with your library? [ Yes / No ] # 是否需要包含一個Demo
> yes
Which testing frameworks will you use? [ Specta / Kiwi / None ]
> none
Would you like to do view based testing? [ Yes / No ]
> no
What is your class prefix?
> AD
現在我們就有了一個 CocoaPods 的模闆工程,它的結構是這樣的:
~/Desktop/本地私有庫 » tree ADFMBase -L 2 jingshi@goodswifter
ADFMBase
├── ADFMBase
│ ├── Assets
│ └── Classes
│ └── ReplaceMe.m
├── ADFMBase.podspec
├── Example
│ ├── ADFMBase
│ ├── ADFMBase.xcodeproj
│ ├── ADFMBase.xcworkspace
│ ├── Podfile
│ ├── Podfile.lock
│ ├── Pods
│ └── Tests
├── LICENSE
├── README.md
└── _Pods.xcodeproj -> Example/Pods/Pods.xcodeproj
10 directories, 5 files
看吧,把源碼拖到
ReplaceMe.m
的同級目錄,執行
pod install
,就完成了本地私有庫和其測試工程。
三 遠端私有庫
現在使用
pod lib create
就可以友善的生成一個本地私有庫了,但是本地私有庫有一定的局限性,例如:
- 需要在 Podfile 檔案中主動指明路徑;
- 版本更新不容易維護;
- 多人開發時,不友善進行合作;
遠端私有庫就可以友善的解決以上的問題,`制作遠端私有庫分為以下幾個步驟:
- 建立私有
遠端倉庫;git
- 建立私有
遠端索引庫;CocoaPods
- 建立
所需要的項目工程檔案,并上傳到Pod
遠端私有庫;git
- 驗證
描述檔案;podspec
- 向私有
遠端索引庫送出CocoaPods
描述檔案;podspec
- 使用
庫;Pod
git
倉庫的建立在此就不在贅述了,本文中我使用
github
做示例,私有
CocoaPods
遠端索引庫實際上也是一個
git
倉庫,現在我們有兩個私有庫,一個用來存放
Pod
庫的源碼,一個用來存放
Pod
庫的描述檔案。
SSH 授權
添加私有索引庫需要使用 SSH 授權,也是和 Git 倉庫一樣的,了解的同學可以跳過這一步驟,首先建立公鑰:
ssh-keygen
然後找到下面的檔案:
~/.ssh/id_rsa.pub
裡面存放的字元就是公鑰了,然後将公鑰添加
github
,連結如下:
https://github.com/settings/keys
添加私有遠端索引庫
現在執行
pod repo
,可以看到下面的資訊:
master
- Type: git (master)
- URL: https://github.com/CocoaPods/Specs.git
- Path: /Users/jingshi/.cocoapods/repos/master
現在我們隻有一個 CocoaPods 遠端索引庫,也是官方的索引庫,下面執行:
-
: 建立私有庫的時候一定要建立注意
檔案.gitignore
pod repo add ADFMSpecs https://github.com/goodswifter/ADFMSpecs.git
此時我們的 CocoaPods 遠端索引庫就安裝好了,到下面的路徑去看一下:
~/.cocoapods/repos
上傳源碼到 Git
還記得 pod lib create 指令嗎?前面我們使用它來制作了本地私有庫,現在它又排上用場了,執行:
pod lib create ADFMBase
源碼拖到
ReplaceMe.m
的同級目錄,它現在看起來應該是這個樣子:
.
├── Assets
└── Classes
└── Category
├── CALayer+PauseAimate.h
├── CALayer+PauseAimate.m
├── UIImage+XMGImage.h
├── UIImage+XMGImage.m
├── UIView+XMGLayout.h
└── UIView+XMGLayout.m
3 directories, 6 files
執行 pod install,就完成了本地私有庫和其測試工程,通過測試之後,我們就可以把這個本地私有庫制作成遠端私有庫了。
首先修改
ADFMBase.podspec
檔案:
Pod::Spec.new do |s|
s.name = 'ADFMBase'
s.version = '0.0.1'
s.summary = 'ADFMBase.'
s.homepage = 'https://github.com/goodswifter/ADFMBase'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'goodswifter' => '[email protected]' }
s.source = { :git => 'https://github.com/goodswifter/ADFMBase.git', :tag => s.version.to_s }
s.ios.deployment_target = '9.0'
s.source_files = 'ADFMBase/Classes/**/*'
end
然後使用品質檢查工具驗證一下,保證在
ADFMBase.podspec
路徑下,執行:
pod lib lint
根據提示修複就好了
-> ADFMBase (0.0.1)
ADFMBase passed validation.
下面執行:
git add .
git commit -m x
然後和遠端倉庫進行關聯:
git remote add origin https://github.com/goodswifter/ADFMBase.git
git pull origin master
git push origin master
最後打标簽
git tag 0.0.1
git push --tags
上傳 Spec 到遠端索引庫
首先執行下面的指令:
pod spec lint
檢驗通過後,提示如下:
然後将
podspec
檔案推到遠端私有索引庫:
pod repo push ADFMSpecs ADFMBase.podspec
- 上傳報錯
pod repo push ADFMSpecs ADFMBase.podspec --allow-warnings
Validating spec
-> ADFMBase (0.0.1)
- WARN | url: The URL (https://github.com/goodswifter/ADFMBasic) is not reachable.
- NOTE | xcodebuild: note: Using new build system
- NOTE | [iOS] xcodebuild: note: Planning build
- NOTE | [iOS] xcodebuild: note: Constructing build description
Updating the `ADFMSpecs' repo
[!] /usr/bin/git -C /Users/jingshi/.cocoapods/repos/ADFMSpecs pull
Your configuration specifies to merge with the ref 'refs/heads/master'
from the remote, but no such ref was fetched.
- 原因 : 建立私有庫的時候沒有建立
檔案.gitignore
- 解決辦法 : 添加
檔案即可.gitignore
現在看一下本地索引庫中是否已經添加成功:
~/.cocoapods/repos
再看一看你的遠端索引庫中是否添加成功,現在搜尋一下本地索引檔案試試:
-> ADFMBase (0.0.1)
ADFMBase.
pod 'ADFMBase', '~> 0.0.1'
- Homepage: https://github.com/goodswifter/ADFMBase
- Source: https://github.com/goodswifter/ADFMBase.git
- Versions: 0.0.1 [ADFMSpecs repo]
現在我們可以找到自己的遠端私有庫了,下面将
Podfile
檔案改成這樣:
source 'https://github.com/goodswifter/ADPodSpecs.git'
source 'https://github.com/goodswifter/ADFMSpecs.git'
platform :ios, '9.0'
target 'Test01' do
use_frameworks!
pod 'ADCategories'
pod 'ADFMBase'
end
執行 pod install,整個遠端私有庫的搭建和使用就完成了。
CocoaPods 庫更新
我們使用遠端私有庫的目的就是為了版本更新和多人開發,那麼遠端私有庫如何進行更新,更新後其他人又如何使用呢?現在我們給
ADFMBase
進行更新,給它再增加一些功能:
.
ADFMBase
│ ├── Assets
│ └── Classes
│ ├── Base
│ │ ├── Base.h
│ │ ├── Sington.h
│ │ ├── XMGConst.h
│ │ └── XMGConst.m
│ ├── Category
│ │ ├── CALayer+PauseAimate.h
│ │ ├── CALayer+PauseAimate.m
│ │ ├── UIImage+XMGImage.h
│ │ ├── UIImage+XMGImage.m
│ │ ├── UIView+XMGLayout.h
│ │ └── UIView+XMGLayout.m
│ └── Tool
│ ├── XMGAlertTool.h
│ ├── XMGAlertTool.m
│ ├── XMGCacheTool.h
│ ├── XMGCacheTool.m
│ ├── XMGDeviceMessage.h
│ ├── XMGDeviceMessage.m
│ ├── XMGNoticeLocal.h
│ └── XMGNoticeLocal.m
├── ADFMBase.podspec
├── Example
├── LICENSE
├── README.md
└── _Pods.xcodeproj -> Example/Pods/Pods.xcodeproj
在
ADFMBase
的測試工程中測試無誤後,将
ADFMBase.podspec
的
version
修改一下:
Pod::Spec.new do |s|
s.name = "ADFMBase"
s.version = "0.1.0"
s.summary = "ADFMBase."
s.homepage = "https://github.com/goodswifter/ADFMBase"
s.license = 'MIT'
s.author = { "goodswifter" => "[email protected]" }
s.source = { :git => "https://github.com/goodswifter/ADFMBase.git", :tag => "#{s.version}" }
s.source_files = "ADFMBase/Classes/**/*.{h,m}"
s.platform = :ios, "9.0" #平台及支援的最低版本
end
現在檢查一下私有庫是否有錯誤:
pod lib lint
檢查通過後就可以将
ADFMBase
的
0.1.0
版本推到遠端私有庫中,同時建立
0.1.0
的 Tag。
然後檢查一下
spec
檔案:
pod spec lint
檢查通過後,執行:
pod repo push ADFMSpecs ADFMBase.podspec
如果存在警告,可以執行:
pod repo push ADFMSpecs ADFMBase.podspec --allow-warnings
遠端私有庫和遠端私有索引庫全部更新完畢,現在我們回到使用者的視角,這個庫可以使用了嗎?還不行。
因為本地的索引檔案還沒有更新,這個源還找不到,現在進入殼工程,執行:
pod update --no-repo-update
ADFMBase
的 0.1.0 版本就乖乖的進入了殼工程。
CocoaPods 庫依賴
如果在我們之前的工程中, 大量使用了
ASI
架構, 大家也都知道,
ASI
架構不再維護, 需要換成别的網絡架構, 例如
AFN
, 但是現在要更換架構的話,
ASI
架構在我們的項目中已經無處不再, 這樣換的話,我們是不是很痛苦呢?
是以我們一般在開發中都會封裝網絡請求,做到分層解耦,這樣如果換架構,隻修改網絡請求這層的封裝就可以了,那麼現在我們需要将
ASI
封裝成
Netwok
,再把
Netwok
弄到我們的
ADFMBase
裡面去,怎麼做呢?
現在先将
Network
拖到
ADFMBase
的 Classes
目錄中,因為
ADFMBase
的測試工程沒有
AFN
,是以
Network` 肯定是會報錯了,不要慌,下面我們修改 spec 檔案:
Pod::Spec.new do |s|
s.name = "ADFMBase"
s.version = "0.3.0"
s.summary = "ADFMBase."
s.homepage = "https://github.com/goodswifter/ADFMBase"
s.license = 'MIT'
s.author = { "goodswifter" => "[email protected]" }
s.source = { :git => "https://github.com/goodswifter/ADFMBase.git", :tag => "#{s.version}" }
s.source_files = "ADFMBase/Classes/**/*.{h,m}"
s.platform = :ios, "9.0" #平台及支援的最低版本
s.dependency 'AFNetworking'
end
dependency
指明了這個庫的依賴,改好之後
pod install
,
AFN
就安裝到了
ADFMBase
的測試工程中,現在就可以使用 AFN 進行網絡請求封裝,直接
import
就可以了
現在再進行一次遠端私有庫更新,整個依賴就做好了
CocoaPods 子庫
現在我們實作了一個完整的遠端私有庫,可以更新,依賴其他的庫,提供給其他人使用,但是現在還有一點問題,其他人如果要用我們的庫,就需要把
ADFMBase
完整的克隆過來,但是他可能隻需要
ADFMBase
裡面的
Network
,其他的擴充、工具等并不想使用,也不想導入過來,怎麼辦?有兩種方案:
- 把
剝離出來,再單獨建一個遠端私有庫;Network
- 使用子庫遷出
;Network
第一種方案大家已經知道了,就是上面的一大篇,麻煩不說,而且東西一多起來,這裡一個庫,那裡一個庫,也不容易管理,是以,下面就有請子庫隆重登場。
注意
Subspecs
這裡,它就是本節要講的東西,首先将
spec
改成下面這樣:
Pod::Spec.new do |s|
s.name = "ADFMBase"
s.version = "0.4.0"
s.summary = "ADFMBase."
s.homepage = "https://github.com/goodswifter/ADFMBase"
s.license = 'MIT'
s.author = { "goodswifter" => "[email protected]" }
s.source = { :git => "https://github.com/goodswifter/ADFMBase.git", :tag => "#{s.version}" }
# s.source_files = "ADFMBase/Classes/**/*.{h,m}"
# 子庫
s.subspec 'Base' do |b|
b.source_files = 'ADFMBase/Classes/Base/**/*'
end
s.subspec 'Category' do |c|
c.source_files = 'ADFMBase/Classes/Category/**/*'
end
s.subspec 'Network' do |n|
n.source_files = 'ADFMBase/Classes/Network/**/*'
n.dependency 'AFNetworking'
end
s.subspec 'Tool' do |t|
t.source_files = 'ADFMBase/Classes/Tool/**/*'
end
s.platform = :ios, "9.0" #平台及支援的最低版本
end
如果依賴的架構隻有某一個子庫,使用,要将依賴放到子庫的spec中
在這裡要注意 source_files 和 dependency 以及版本的變化,修改完成推到遠端索引庫,并打好 0.4.0 的分支,執行:
pod spec lint
pod repo push ADFMSpecs ADFMBase.podspec
pod update --no-repo-update
pod search ADFMBase
CocoaPods 資源依賴
現在我們可以讓一個庫依賴另外一個庫,但是看下面這段代碼:
這段代碼讀取了一個 XIB 檔案,這個庫的結構是這樣的:
.
├── Assets
└── Classes
├── Controller
│ ├── ADNavVC.h
│ ├── ADNavVC.m
│ ├── ADTabBarVC.h
│ └── ADTabBarVC.m
└── View
├── ADMiddleView.h
├── ADMiddleView.m
├── ADMiddleView.xib
├── ADNavBar.h
├── ADNavBar.m
├── ADTabBar.h
└── ADTabBar.m
們可以成功調用這個方法嗎?不能,因為
ADMiddleView.xib
這個檔案的
Target
是
MainModule
,使用
CocoaPods
把這個庫安裝到我們項目後,
XIB
檔案即使在,也是在
Pods
這個工程裡,而我們在殼工程中使用
ADMiddleView.xib
,也是必然找不到的。
下面我們把模闆庫的測試工程編譯一下,打開
Products
目錄下的
.app
檔案,看一下檔案結構:
.
├── ADFMMain_Example
├── Assets.car
├── Base.lproj
│ └── LaunchScreen.storyboardc
├── Frameworks
│ ├── ADFMMain.framework
│ │ ├── ADFMMain
│ │ ├── ADFMMain.bundle
│ │ │ ├── Info.plist
│ │ │ ├── _CodeSignature
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ ├── ADMiddleView.nib
│ │ ├── Info.plist
│ │ └── _CodeSignature
├── Info.plist
├── PkgInfo
├── _CodeSignature
└── en.lproj
通過路徑可以看到,
ADMiddleView.nib
是在:
mainBundle/Frameworks/ADFMMain.framework/ADMiddleView.nib
這個路徑下面,是以
mainBundle
中肯定是找不到資源檔案的,那麼該如何修改呢?
+ (instancetype)middleView {
NSBundle *currentBundle = [NSBundle bundleForClass:self];
return [[currentBundle loadNibNamed:NSStringFromClass(self) owner:nil options:nil] firstObject];
}
這部分的重點就是
[NSBundle bundleForClass:self]
這個方法。
CocoaPods 圖檔依賴
上面我們講到了怎樣使用 Pod 庫裡面的 XIB 檔案,但是還有其他資源檔案,例如圖檔、音頻、視訊,圖檔我們一般是放在 Assets.xcassets,但是 Pod 庫并沒有對應的路徑,那麼它所需要的圖檔放在哪裡,已經如何使用呢?現在使用 pod lib create 指令建立一個 Pod 庫,進入以下路徑:
把一些圖檔拖入到
Assets
檔案夾内,然後在
podspec
檔案中加入以下代碼
s.resource_bundles = {
'元件名' => ['元件名/Assets/*.png'] //隻加載 png 檔案
# '元件名' => ['元件名/Assets/*'] //加載所有檔案
}
然後執行
pod install
,
Pod
庫中就出現了之前拖入
Assets
檔案夾的圖檔,但是現在還不能使用,我們先來看一下打包以後這些圖檔的路徑:
.
├── ADFMMain_Example
├── Assets.car
├── Base.lproj
│ └── LaunchScreen.storyboardc
├── Frameworks
│ ├── ADFMMain.framework
│ │ ├── ADFMMain
│ │ ├── ADFMMain.bundle
│ │ │ ├── Info.plist
│ │ │ ├── _CodeSignature
│ │ │ ├── [email protected]
│ │ │ ├── [email protected]
│ │ ├── ADMiddleView.nib
│ │ ├── Info.plist
│ │ └── _CodeSignature
├── Info.plist
├── PkgInfo
├── _CodeSignature
└── en.lproj
可以看到,打包後的路徑在:
mainBundle/Frameworks/ADFMMain.framework/ADFMMain.bundle
複制代碼這個路徑下面,而代碼中的
[UIImage imageNamed:@"xxx.png"]
讀取的是
mainBundle
下的資源檔案,是以還是找不到的,那麼這時使用圖檔,應該将代碼改成這樣:
NSInteger scale = [[UIScreen mainScreen] scale];
NSBundle *currentBundle = [NSBundle bundleForClass:self];
NSString *fullImageName = [NSString stringWithFormat:@"%@@%zdx", imageName, scale];
NSString *currentBundleName = [currentBundle.infoDictionary[@"CFBundleName"] stringByAppendingString:@".bundle"];
NSString *path = [currentBundle pathForResource:fullImageName ofType:@"png" inDirectory:currentBundleName];
path ? [UIImage imageWithContentsOfFile:path] : nil;
這裡需要注意的是,檔案名需要完整。以上是在代碼中加載圖檔,如果是在
XIB
中加載圖檔,應該怎樣做呢?那麼再看一下上面的目錄結構,
ADFMMain.nib
和
ADFMMain.bundle
處于同一個目錄,我們可以在
ADFMMain.xib
中通過相對路徑,使用
ADFMMain.bundle
裡面的圖檔,是以在 XIB 中,圖檔名應該是這樣的:
ADFMMain.bundle/[email protected]