- 隨著公司業務的不斷髮展,應用的程式碼體積將會越來越大,業務程式碼耦合也越來越多,程式碼量也是急劇增加
- 如果僅僅完成程式碼拆分還不足以解決業務之間的程式碼耦合,而元件化是一種能夠解決程式碼耦合、業務工程能夠獨立執行的技術
- 這篇文章主要介紹遠端私有庫的建立和管理以及本地索引庫的使用, 並且可參照釋出開源框架到CocoaPods入坑指南
- 個人原文部落格地址: iOS元件化之私有庫
本地庫方案
建立本地私有庫
- 首先需要一個宿主工程
MainMoudle
和一個用於存放所有本地私有庫的資料夾AllMoudles
, 這兩個資料夾在同一目錄下 - 在
AllMoudles
資料夾中建立一個私有庫TitanFMBase
, 在子目錄建立Classes
用於存放所有的檔案, 目錄如下:AllMoudles/TitanFMBase/Classes
- 在
Classes
資料夾中新增檔案, 並提交到本地git
//進入TitanFMBase資料夾
cd xxx/AllMoudles/TitanFMBase
//初始化git
git init
//將原生程式碼提交到本地倉庫
git add .
// 提交修改到本地倉庫
git commit -m '你的修改記錄'
//建立spec檔案
pod spec cteate TitanFMBase
複製程式碼
最後開啟TitanFMBase
資料夾中的TitanFMBase.podspec
, 修改對應的配置資訊, 可參考修改部落格
注意點
在source
配置中, 本地庫的git地址不需要填
s.source = { :git => "", :tag => "#{s.version}" }
複製程式碼
使用本地私有庫
- 安裝和使用本地私有庫和和遠端私有庫步驟一樣, 不同的是:
- 遠端私有庫不需要指明庫的地址
- 本地私有庫需要制定庫地址(相對路徑即可)
- 使用
path
的形式新增框架依賴
pod 'TitanFMBase', :path => '../AllMoudles/TitanFMBase'
複製程式碼
注意點
- 入夥時本地私有庫, 不需要使用
pod lib lint
或者pod spec lint
驗證spec
檔案的正確性 - 因為有些欄位只有遠端私有庫才需要設定, 只要保證本地私有庫的路徑正確, 並不影響使用
遠端私有庫
- 當我們在終端執行
pod search
命令時, 搜尋的其實是本地快取的spec
檔案, 當然第一次使用時需要先更新本地的spec
檔案 - 可在終端執行
pod repo
命令檢視當前本地的索引庫, 或者檢視目錄~/.cocoapods/repos/master/Specs
- 在元件化開發過程中, 為防止程式碼洩露, 我們必須要建立自己的本地索引庫
- 釋出開源框架到CocoaPods入坑指南文章中提到了一種建立方式
- 但是上述提到的建立方式, 需要手動建立
podspec
檔案 - 需要手動進行git管理, 不能測試, 需要手動新增測試工程
- 但是上述提到的建立方式, 需要手動建立
- 執行
pod repo add TitanSpec http://xxxx
命令, 可建立一個新的本地索引庫 - 建立遠端索引庫, 碼市
- 除圖中紅色箭頭外, 其他地方不需要填寫, 新建即可
建立遠端私有庫
pod lib create xxx
- 規範建立私有庫, 執行上述命令, 可同時建立
spec
檔案和測試工程等 - 根據提示建立不同的配置檔案即可, 建立完成後, 將需要新增的私有庫檔案放到
xxx/xxx/Classes
資料夾下即可, 預設建立的.m檔案可刪除 - 最後需要開啟
Example
目錄下的測試工程, 並執行pod install
命令, 將你的私有庫檔案安裝到測試工程 - 最後修改
xxx
檔案下的xxx.podspec
檔案中相關配置即可
做完上述工作即可將專案所有檔案提交到遠端私有庫了
// 將原生程式碼加入本地倉庫裡
git add .
// 提交修改到本地倉庫
git commit -m '你的修改記錄'
// 檢視當前的遠端連線
git remote
// 新增名稱為origin的遠端連線
git remote add origin '你的github專案地址'
// 在push之前, 檢視spec是否配置有問題
// 驗證本地spec檔案是否有誤
pod lib lint
// 驗證遠端spec檔案是否有誤
pod spec lint
// 推送master分支的程式碼到名稱為origin的遠端倉庫
git push origin master
複製程式碼
- 正常情況下本地驗證一般沒問題, 遠端驗證正常情況下會有問題
- 本地驗證不會驗證
s.source
後面的tag
- 遠端驗證會驗證
tag
, 而至此我們的tag
還沒有設定, 所以驗證不會通過, 需要打標籤 - 設定好
tag
, 再次驗證應該就是沒問題的了
// 檢視當前的tag值
git tag
// 設定tag值
git tag "0.0.1"
// 上傳提交tag
git push --tags
// 刪除標籤相關命令
// 先刪除本地再刪除遠端標籤, 刪除後需要重新打標籤
// 刪除本地標籤
git tag -d 0.0.1
// 刪除遠端標籤
git push origin :0.0.1
複製程式碼
提交私有的SpecRepo
向私有的SpecRepo
中提交podspec
:
pod repo push SpecName XXX.podspec
複製程式碼
注意點
- 提交
podspec
的過程中會有驗證, 最好在提交之前先驗證spec
檔案的配置是有問題pod lib lint
- 警告可以使用
--allow-warings
忽略 - 但是涉及到的錯誤資訊一定要解決
- 警告可以使用
- 提交過程中, 會提交資訊到遠端私有索引庫
使用私有庫
- 檢索私有庫:
pod search XXX
- 如果檢索不到, 可以先到私有索引庫內, 看看是否存在私有庫
- 如果存在還是檢索不到, 則直接刪除私有庫索引檔案, 重新配置
- 在
Podfile
檔案中, 同事使用私有庫和第三方庫是需要指定對應的source
源 pod repo
命令執行後的結果
master
- Type: git (master)
- URL: 'https://github.com/CocoaPods/Specs.git'
- Path: /Users/xxx/.cocoapods/repos/master
TitanFMSpec
- Type: git (master)
- URL: 'https://git.coding.net/CoderTitan/TitanFMSpec.git'
- Path: /Users/xxx/.cocoapods/repos/TitanFMSpec
複製程式碼
Podfile
檔案中配置資訊
// 遠端私有庫
source 'https://git.coding.net/CoderTitan/TitanFMSpec.git'
// 官方倉庫
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
target 'TitanjunFM' do
use_frameworks!
pod 'TitanFMBase'
pod 'MJExtension'
end
複製程式碼
更新私有庫
更新遠端私有庫
- 修改
xxx/xxx/Classes
資料夾下對應的庫檔案 - 更新測試工程的
Pod
庫檔案:pod update --no-repo-update
- 更新
xxx.podspec
檔案的配置資訊, 版本號一定要改 - 提交程式碼到遠端倉庫:
git push origin master
- 更新
tag
標籤:git push --tags
- 更新遠端和本地的私有索引庫:
pod repo push SpecName XXX.podspec
私有庫依賴
初步設計方案
- 在設計私有庫的過程中難免可能會涉及到使用其他第三方庫的情況, 又該如何解決這種問題
- 新增元件依賴: 在
podspec
檔案配置中, 新增如下依賴程式碼
s.dependency 'AFNetworking'
s.dependency 'SDWebImage'
複製程式碼
- 注意依賴, 以及框架標頭檔案中, 不要直接匯入依賴框架的標頭檔案
- 也就是說, 上述涉及到的所依賴的第三方庫, 在專案的
Podfile
檔案中, 不會再匯入該類庫
優化方案
上述方案存在的問題: 假如另外一個業務線, 僅僅需要依賴一些基礎配置, 但是, 如果把整個庫作為依賴, 便會匯入一些不用的冗餘程式碼
- 這樣, 我們現在終端執行
pod search AFNetworking
, 看一下AFNetworking
的搜尋結果 - 會看到
Subspecs
中, 將AFNetworking
分成了幾個不同的部分, 這樣我們就可以根據不同的功能需求匯入不同部分的程式碼即可, 防止程式碼冗餘
-> AFNetworking (3.2.1)
A delightful iOS and OS X networking framework.
pod 'AFNetworking', '~> 3.2.1'
- Homepage: https://github.com/AFNetworking/AFNetworking
- Source: https://github.com/AFNetworking/AFNetworking.git
- Versions: 3.2.1, ......,0.5.1 [master repo]
- Subspecs:
- AFNetworking/Serialization (3.2.1)
- AFNetworking/Security (3.2.1)
- AFNetworking/Reachability (3.2.1)
- AFNetworking/NSURLSession (3.2.1)
- AFNetworking/UIKit (3.2.1)
複製程式碼
為解決將私有庫中的程式碼分成不同的功能模組, 使用
subspec
語法配置podspec
檔案, 如下:
//格式:
s.subspec 'XXX' do |x|
//需要匯入的所有檔案的相對路徑
x.source_files = '相對路徑/**/*'
//需要匯入的.h標頭檔案的相對路徑
x.public_header_files = '相對路徑/**/*.h'
//需要匯入的資原始檔的相對路徑
x.resource = "相對路徑/**/*.{bundle,nib,xib}"
//所依賴的其他的庫
x.dependency 'AFNetworking', '~> 1.0.0'
end
//示例:
s.subspec 'Network' do |n|
n.source_files = 'TitanFMBase/Classes/Network/**/*'
n.dependency 'AFNetworking'
end
複製程式碼
- 將原來的
s.source_files
改成上述語法即可 - 外部使用時只需匯入
pod 'AFNetworking/Reachability'
即可
私有庫的資源引用
xib&storyboard
- 所有私有庫中的
xib
必須動態獲取 - 私有庫中引用圖片資源或者
Xib
資源時, 又該如何引用呢? - 都知道專案中引用
Xib
時, 通常方式是[[NSBundle mainBundle] load]
方式, 但是這種方式在私有庫中顯然不適用 - 在私有庫中載入私有庫中的
XIb
, 使用方法[NSBundle bundleForClass:self]
動態獲取, 具體看一下
// MiddleView.m
NSBundle *mainBundle = [NSBundle mainBundle];
NSBundle *bundle = [NSBundle bundleForClass:self];
MiddleView *middleView = [[bundle loadNibNamed:@"MiddleView" owner:nil options:nil] firstObject];
// 列印一下上述兩個bundle如下:
// mainBundle:
NSBundle </Users/xxx/Library/Developer/CoreSimulator/Devices/6B74958F-560F-4BF4-9BDF-9AD789379FC9/data/Containers/Bundle/Application/FC9747F0-8A82-4643-AC7E-BDC268190B8D/TitanFM.app>
// bundle:
NSBundle </Users/xxx/Library/Developer/CoreSimulator/Devices/6B74958F-560F-4BF4-9BDF-9AD789379FC9/data/Containers/Bundle/Application/FC9747F0-8A82-4643-AC7E-BDC268190B8D/TitanFM.app/Frameworks/TitanFMMain.framework>
複製程式碼
- 從上述資訊中可以看到, 專案中正常的
Xib
等資原始檔是放在TitanFM.app
中的 - 而私有庫的
Xib
等資原始檔是放在TitanFM.app/Frameworks/TitanFMMain.framework
檔案目錄下的, 所以私有庫中的資原始檔載入, 要到對應的檔案目錄下 - 具體也可以到
TitanFM.app
中檢視, 找到對應的app
檔案, 顯示包內容, 即可層級檢視
圖片資源
圖片存放問題
- 正常專案中, 我們的圖片一般都會放在類似字尾
.xcassets
的檔案中 - 在設計私有庫時, 在
Classes
的同級目錄中會預設建立一個Assets
的資料夾, 用於存放圖片等資源 - 在
podspec
檔案中, 同樣修改載入檔案資源的配置, 如下:
s.resource_bundles = {
'MainMoudle' => ['MainMoudle/Assets/*']
}
複製程式碼
修改完配置資訊和圖片記得執行
pod install
把資原始檔匯入到專案中
私有庫圖片的使用
在xib
中載入圖片, 需要在圖片前面加上元件的主bundle
, 類似: MainMoudle.bundle/tabbat_back
私有庫中使用程式碼載入圖片, 一定不能使用imageNamed
方法
//1. 獲取當前的bundleName
NSBundle *currentBundle = [NSBundle bundleForClass:[self class]];
//2. 根據圖片名稱, 在bundle中檢索圖片路徑
NSString *path = [currentBundle pathForResource:@"tabbar_np_play@2x.png" ofType:nil inDirectory:@"MainMoudle.bundle"];
//獲取圖片
UIImage *image = [UIImage imageWithContentsOfFile:path];
複製程式碼
引用圖片需要注意的的是
- 圖片引用過程中不會自動選擇
@2x和@3x
的圖片, 所以必須手動指定具體的圖片名稱包括圖片字尾名 - 獲取路徑的方法
pathForResource
, 也要必須指明圖片所在的bundle
路徑, 即inDirectory
引數不可為空
提交本地的私有庫索引
- 當你的私有庫中引用了其他的私有庫框架, 比如
MainMoudle
中引用了TitanFMBase/Category
部分 - 則切記不要進行本地和遠端的
spec
驗證, 否則可能回報錯, 原因只是因為spec
中預設的依賴庫是共有的索引庫, 私有庫無法檢索到, 錯誤資訊如下圖 - 提交本地索引的過程中遇到類似錯誤則可以, 直接忽略提交即可, 但是其他的錯誤資訊, 切記需要修改好, 警告可以忽略, 但是錯誤資訊不能忽略(依賴私有庫的問題除外)
// 提交本地私有索引庫需要忽略警告的命令
pod repo push TitanjunSpec MainMoudle.podspec --allow-warnings
複製程式碼