最近公司項目開始推動子產品化了,雖然iOS的多工程聯編已經是一個老技術了,自己以前也做過簡單的demo,但是在實際落地過程中還是遇到了很多奇奇怪怪的問題,在這裡做一下總結和記錄。首先會大概講一下cocoapods實作子產品化的一個大緻原理和過程,然後會把自己在實作過程遇到的問題做一下記錄。
目錄
cocoapods的結構
建立自己的元件庫
建立和更新索引庫
遇到的問題和解決方法
私有庫内部的子子產品互相依賴的寫法
podspec檔案中依賴系統framework和library的方法
私有庫中如何加載圖檔?
cocoapods的結構
cocoapods可以了解成所有元件的管理者,管理方式是通過一個索引倉庫(podspec庫),所有想要加入cocoapods官方庫的元件都要提供一個podspec檔案,該檔案即是該元件在cocoapods官方倉庫中的唯一索引,同時源碼倉庫中的檔案結構也要符合cocoapods的規定。當我們安裝cocoapods時,會在我們的根目錄下生成一個.cocoapods的檔案夾,并将cocoapods的官方倉庫克隆至該檔案夾下,往後cocoapods會根據這個倉庫中的索引檔案将相應的元件內建進我們的工程中。
建立自己的元件庫
之是以要建立我們自己的元件庫,是因為子產品化過程中,我們需要将不同的業務功能從主工程中剝離出來做成一個個靜态庫工程,然後将這些獨立的業務功能子產品以子工程的形式內建進主工程中,但是業務功能子產品都需要用到的基礎功能元件卻不可能每個子工程都複制一份,比如自定義的相冊、自定義的時間選擇器、控制器基類等等,這些基礎元件需要我們将其做成一個cocoapods私有庫維護起來。
1.建立一個倉庫,可以是git或者svn,都是可以的
2.使用pod指令建立私有庫工程
pod lib create {你的私有庫名稱}
是否建立一個demo項目這個選項,建議選擇yes。最終建立的私有庫工程目錄結構如下:
在Example檔案夾中可以打開我們的demo工程
Classes檔案夾就是我們更新維護私有庫的工作目錄。
3.将podspec檔案中的source換成我們的倉庫位址,然後将私有庫工程送出到剛才建立的遠端倉庫并打上tag,tag必須和podspec檔案中的version相一緻,至此我們的私有庫就已經可以使用了。
雖然可以使用,但是工程中我們的私有庫目錄會很難看
原因顯而易見,我們在podspec檔案中不做任何處理的将Classes檔案夾中的所有檔案都引入了,是以元件A群組件B都混在了一起。
這一點我們可以做的更好,比如這樣:
通過subspec來做分層,這樣浏覽起來更加清晰,實體檔案路徑上也要做相應的調整。
看起來麻煩一點,但是更符合元件的開發維護的規範
建立和更新索引庫
實際使用中隻要有代碼庫就已經可以在pod中直接導入我們的項目了。
pod 'WLPodTest', :git => 'http://github.com/bigKumasann/WLPodTest.git', :tag => '0.1.0'
我之是以要使用索引庫,一是為了好看和友善管理,更重要的原因是我的項目中有多個私有庫,且存在私有庫依賴私有庫的情況,這種就隻能建立索引庫了,因為podspec的文法中,dependency是無法通過git位址+tag或者branch這種方式來依賴其他私有或者公有庫的。
建立索引庫首先需要建立一個存放podspec檔案的遠端倉庫,然後通過pod指令将索引庫克隆到本地的.cocoapods/repos檔案夾下。
pod repo add REPO_NAME SOURCE_URL
例如:pod repo add MallRepo http:***********.git
如圖所示,該指令會将我們的索引庫clone到本地的.cocoapods/repos路徑下面。然後我們通過以下指令行将我們的私有庫podspec檔案上傳到索引庫中。
pod repo push REPO_NAME {podspec檔案所在的實體路徑} --allow-warnings
pod repo push MallRepo WLPodTest.podspec --allow-warnings
之後如果WLPodTest庫有更新的話也是通過該指令進行索引庫的更新。
podspec檔案上傳成功後,其他私有庫就可以在podspec檔案中依賴WLPodTest了
s.dependency private_framework_name, version
s.dependency 'WLPodTest', '0.1.0'
但是需要在podfile檔案中分别指定官方索引庫和私有索引庫位址
source 'https://github.com/CocoaPods/Specs.git'
source {YOUR_REPO_URL}
那麼,依賴WLPodTest私有庫的其他私有庫怎麼維護上傳自己的podspec檔案呢?
pod repo push REPO_NAME {podspec檔案所在的實體路徑} --allow-warnings
實踐證明并不能通過以上指令上傳podspec檔案,因為{pod repo push}指令會校驗podspec中的依賴,此時會因為找不到依賴的WLPodTest私有庫而報錯,是以我們需要在{pod repo push}後面提供所依賴的其他庫的索引庫位址
pod repo push private_repo --sources=https://github.com/CocoaPods/Specs.git,{私有索引庫位址} --allow-warnings
pod repo push MallRepo --sources=https://github.com/CocoaPods/Specs.git, *****.git --allow-warnings
遇到的問題和解決方法
私有庫内部的子子產品互相依賴的寫法
ss.dependency = spec名稱/subspec名稱
注意這次并不是通過實體路徑來指定所依賴的子產品在哪的,我在這裡被困擾了很久。
podspec檔案中依賴系統framework和library的方法
從上文中我們知道依賴第三方庫使用dependency指定,那麼依賴系統庫(Library)或者系統架構(Framework)呢?
依賴Library隻需要通過.libraries來指定,指定時将系統庫的lib字首去掉,如依賴libxml2.tbd和libsqlite3.tbd。
s.libraries = "sqlite3", "xml2"
依賴系統架構framework有兩種場景,系統架構在iOS中被分為了兩個部分,如下圖所示
1.Frameworks路徑下有我們經常使用的UIKit和Foundation架構,該路徑下的系統架構通過frameworks指定,如下所示。
s.ios.frameworks = 'UIKit', 'Foundation'
2.usr/include路徑下的系統架構需要通過實體路徑指定頭檔案查找路徑。例如我們經常使用的runtime架構就在usr/include路徑下面,指定方法如下。
s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/objc" }
私有庫中如何加載圖檔?
如果所要展示的本地圖檔也在私有庫中,當然不能使用imageNamed方法建立UIImage對象了,因為imageNamed方法會預設從mainbundle中尋找圖檔。
在podspec檔案中有兩種方式将圖檔引入pod工程,隻能使用其中一種方式,否則會報錯。
方法一:
s.resource_bundles = {
'mallPods' => ['mallPods/Assets/*.png']
}
方法二:
s.resource = 'mallPods/Assets/mallPods.bundle'
然後通過如下代碼查找到圖檔路徑
//加載目前 bundle
NSBundle *mallPodsBundle = [NSBundle bundleWithPath:[[NSBundle bundleForClass:[RTRootNavigationController class]] pathForResource:@"mallPods" ofType:@"bundle"]];
//檔案路徑
NSString *imagePath = [mallPodsBundle pathForResource:@"[email protected]" ofType:@"png"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
最終圖檔檔案所在的路徑是:
/var/containers/Bundle/Application/4DBEE065-AE93-4163-9DB1-3EAB05CFCE55/mallPods_Example.app/Frameworks/mallPods.framework/mallPods.bundle/[email protected]
方法二需要我們自己建立一個mallPods.bundle檔案,方法一則由cocoapods幫助我們生成一份bundle檔案,但需要我們指定bundle名稱。最終這份bundle檔案會被放在我們的私有庫framework下面。
以上就是我在項目元件化過程中遇到的問題和總結了,希望可以幫到某些也在做元件話的小夥伴。