iOS組件化之私有庫

  • 隨着公司業務的不斷髮展,應用的代碼體積將會愈來愈大,業務代碼耦合也愈來愈多,代碼量也是急劇增長
  • 若是僅僅完成代碼拆分還不足以解決業務之間的代碼耦合,而組件化是一種可以解決代碼耦合、業務工程可以獨立運行的技術
  • 這篇文章主要介紹遠程私有庫的建立和管理以及本地索引庫的使用, 而且可參照發佈開源框架到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, 修改對應的配置信息, 可參考修改博客html

注意點ios

source配置中, 本地庫的git地址不須要填git

s.source = { :git => "", :tag => "#{s.version}" }
複製代碼

使用本地私有庫

  • 安裝和使用本地私有庫和和遠程私有庫步驟同樣, 不一樣的是:
    • 遠程私有庫不須要指明庫的地址
    • 本地私有庫須要制定庫地址(相對路徑便可)
  • 使用path的形式添加框架依賴
pod 'TitanFMBase', :path => '../AllMoudles/TitanFMBase'
複製代碼

注意點github

  • 入夥時本地私有庫, 不須要使用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命令, 可建立一個新的本地索引庫
  • 建立遠程索引庫, 碼市
  • 除圖中紅色箭頭外, 其餘地方不須要填寫, 新建便可

CreateSpec

建立遠程私有庫

  • pod lib create xxx
  • 規範建立私有庫, 執行上述命令, 可同時建立spec文件和測試工程等
  • 根據提示建立不一樣的配置文件便可, 建立完成後, 將須要添加的私有庫文件放到xxx/xxx/Classes文件夾下便可, 默認建立的.m文件可刪除
  • 最後須要打開Example目錄下的測試工程, 並執行pod install命令, 將你的私有庫文件安裝到測試工程
  • 最後修改xxx文件下的xxx.podspec文件中相關配置便可

createLib

作完上述工做便可將項目全部文件提交到遠程私有庫了緩存

// 將本地代碼加入本地倉庫裏
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:bash

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文件中配置信息app

// 遠程私有庫
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
複製代碼

更新私有庫

更新遠程私有庫

  1. 修改xxx/xxx/Classes文件夾下對應的庫文件
  2. 更新測試工程的Pod庫文件: pod update --no-repo-update
  3. 更新xxx.podspec文件的配置信息, 版本號必定要改
  4. 提交代碼到遠程倉庫: git push origin master
  5. 更新tag標籤: git push --tags
  6. 更新遠程和本地的私有索引庫: 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

xibimage

私有庫中使用代碼加載圖片, 必定不能使用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
複製代碼

podspec

相關參考


歡迎您掃一掃下面的微信公衆號,訂閱個人博客!

微信公衆號
相關文章
相關標籤/搜索