- 繼續整合:一個主工程(殼工程),包含所有的內容(整個專案),用於發包或打包測試。
- 基礎元件: 不依賴其他任何元件,獨立完成功能。主要有:*與業務無法的功能(如string或data的加密,category的封裝) *對第三方庫的封裝(如AFNetworking,SDWebImage的封裝)
- 業務公用元件:依賴基礎元件或UIKit等系統元件,建立業務共同使用的功能(如分享,支付,網路訪問)
- 中間元件:連線業務公用元件和業務元件,及業務元件之間的互相呼叫。(如Mediator的元件)
- 業務元件:單獨的業務功能,不依賴其他業務元件。
大致的框架思路,其中會碰到一個顆粒度的問題,將顆粒度設定過大,則元件之間的耦合性過大,顆粒度設定過小,則將產生很多的元件和中間元件,元件的管理成本過大。(具體問題需要具體分析)
一、 Cocoapods的元件管理
1. pod spec檔案建立
Pod::Spec.new do |spec|
spec.name = 'Reachability' spec.version = '3.1.0'
spec.license = { :type => 'BSD' }
spec.homepage = 'https://github.com/tonymillion/Reachability'
spec.authors = { 'Tony Million' => 'tonymillion@gmail.com' }
spec.summary = 'ARC and GCD Compatible Reachability Class for iOS and OS X.'
spec.source = { :git => 'https://github.com/tonymillion/Reachability.git', :tag => 'v3.1.0' }
spec.source_files = 'Reachability.{h,m}'
spec.framework = 'SystemConfiguration'
end
複製程式碼
根據內容編寫專案的資訊,小的細節可以學習Git上支援Cocoapods的專案,檢視專案中*.spec檔案。
如:
(1). 新增資原始檔使用 s.resource_bundles
(2). 需要新增多個檔案,使用陣列s.source_files = ['ThirdSdk/Classes/**/*.{h,m}', 'ThirdSdk/Classes/**/**/*.{h,m}']
2. LICENSE和README.md檔案
編寫許可證和說明的檔案。最好參考官方的寫法,不然檢測不過。
3.建立一個Example工程
關鍵一個Example的工程,在Podfile中採用直接引用Module檔案進行元件的開發。方便對單個元件進行除錯
如pod 'ThirdSdk', :path => '../'
4.本地資料庫(cocoapods映象)建立
新建一個Git庫,取名Specs用來儲存本地的所有私有庫。
使用pod repo add [name] [Git地址]
新增一個私有Cocoapods Specs映象。
使用pod repo push REPO [NAME.podspec]
將私有元件推送到私有第三方庫映象。
5.依賴第三方庫
在Podfile檔案中可以新增依賴的第三方庫,包括Cocoapods和私有本地的庫。
platform :ios, '7.0'
source 'git@code.*.com:ios/Specs.git'
source 'https://github.com/CocoaPods/Specs.git'
target 'ThirdSdk_Example' do
pod 'ThirdSdk', :path => '../'
#cocoapods specs
pod 'AliyunOSSiOS'
#local specs
pod 'WebService'
end
複製程式碼
其中
- (1)
source 'git@code.*.com:ios/Specs.git'
是申請引用本地指定的資料地址。 - (2)
source 'https://github.com/CocoaPods/Specs.git'
是cocoapods官方的第三方庫資料地址。 - (3)
pod 'AliyunOSSiOS'
引用的是Cocoapods的第三方庫。 - (4)
pod 'WebService'
引用的是私有的第三方庫。
二、元件之間的依賴
(1)對於基礎元件的依賴,採用Pod 直接導致,在程式碼中進行import標頭檔案。這個方式會導致基礎元件的耦合性比較高。可以將元件的顆粒度設定的小一些,儘量抽取出不依賴其他元件的獨立元件。再將這些獨立的元件打包成一個較大的元件,方便管理。如Podfile中
#local specs
pod 'Account'
pod 'AppPod'
pod 'WebService'
複製程式碼
其中的AppPod就是集合,包含很多獨立的基礎元件。
(2)如果是業務元件,在不同的業務之間,一定要避免元件間耦合,採用Mediator
元件作為中介軟體,降低耦合。 具體可以參考[iOS應用架構談 開篇](casatwy.com/iosying-yon…) 提供的Demo編寫。
三、主工程
主工程(殼工程)引用所有的元件,並實現應用的工程。
iOS應用框架及Cocoapods內容的參考:
- casatwy.com/iosying-yon…
- www.cocoachina.com/ios/2016010…
- gracelancy.com/blog/2016/0…
- blog.csdn.net/xyxjn/artic…
- pingguohe.net/2015/11/24/…
- studentdeng.github.io/blog/2013/0…
- ishalou.com/blog/2012/1…
- stackoverflow.com/questions/2…
- www.cnblogs.com/Mr-ios/p/53…
補充
1. 使用pod install 更新失敗的處理
在使用Cocoapods管理程式碼的時候,如果在GitHut上更新了程式碼,希望在project中執行pod install 來重新整理程式碼,那麼需要 刪除Pods和Podfile.lock檔案 然後在執行pod install 來重新整理程式碼
使用pod update進行repo的更新
多次安裝pod install 會出現Build Phase裡多個Check Pods Manifest.lock的選項,這些選項可以刪除。
刪除這個目錄下的快取檔案,進行第三方庫檔案的重新獲取 /Users/*/Library/Caches/CocoaPods/Pods/*
因為有可能因為版本號,沒有增加,在Pods目錄下的VERSION儲存了這個版本的第三方庫,那麼將直接返回已經快取的檔案。所以當私有元件有程式碼修改後,則可以清空這個資料夾下的目錄,來進行私有元件的更新。???(研究了很久才發現這個終極解決方法)
2. Pod中生成資料夾形式或建立子元件
在*.podspec檔案中,根據功能建立不同的子元件,如AFN中的
s.subspec 'Security' do |ss|
ss.source_files = 'AFNetworking/AFSecurityPolicy.{h,m}'
ss.public_header_files = 'AFNetworking/AFSecurityPolicy.h'
ss.frameworks = 'Security'
end
複製程式碼
生成的效果
這種方式也是子元件的方法,在pod中可以直接引用AFSecurityPolicy的元件,如pod 'AFNetworking/Security'
此時僅僅引用的是Security元件,而不是整個AFN元件
在開發是看到的元件,資料夾會比較亂,當其他元件pod後,看到的資料夾就如AFNetworking一樣的效果。
3. *.podspec的dependency使用
元件可以依賴其他的第三方庫,如s.dependency 'JTObjectMapping'
AFNetworking等。
同時也可以依賴私有的第三方庫:
(1)使用pod repo add [name] [Git地址]
新增一個私有Cocoapods Specs映象。
(2)使用pod repo push REPO [NAME.podspec]
將私有元件推送到私有第三方庫映象。
(3)在元件中就可以將已經上傳的元件可以用來依賴了。
4. ThirdSdk元件
在ThirdSdk元件中,不能包含業務或專案相關的類,不然會導致互相依賴。僅僅包含第三方庫的程式碼,可以降低耦合性。 如果能用Cocoapods管理的第三方庫,儘量使用Cocoapods吧。
5. 載入靜態庫和framework
ss.vendored_frameworks = 'ThirdSdk/AlipaySDK/AlipaySDK.framework'
ss.vendored_libraries = 'ThirdSdk/AlipaySDK/libcrypto.a', 'ThirdSdk/AlipaySDK/libssl.a'
複製程式碼
a檔案不是一個source_files。
6. runtime不能返回Bool等基礎資料型別
return [target performSelector:action withObject:params];
複製程式碼
如果返回的值是Bool或其他的基礎資料型別,那麼將會Crash。
需要將返回值設定為NSObject物件型別或nil。
7. 元件中獲取xib,png等resource時,bundle重新設定
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *bundlePath = [bundle pathForResource:@"StoreLocation" ofType:@"bundle"];
if (bundlePath) {
bundle = [NSBundle bundleWithPath:bundlePath];
}
複製程式碼
其中StoreLocation是與podSpec中的s.resource_bundles裡設定的保持一致。
s.resource_bundles = {
'StoreLocation' => ['StoreLocation/Assets/**/*', 'StoreLocation/Classes/Address/*.{xib}'']
}
複製程式碼
8. 圖片和URL的處理
1、每一個元件需要用到的圖片,都放到元件的Assets資料夾中。
在iOS8及更高系統,元件中Xib訪問image會從元件的Assets中讀取。但是iOS7系統,Xib還是從[NSBundle mainBundle]
的Assets中讀取檔案。
2、URL 不單獨放到一個標頭檔案中,放入元件的ViewModel中。
9. TAG的重新整理
當有多人合作開發,TAG又一直維持在1.0.0時,那麼需要每次更新所有的TAG。
需要選中“抓取並在本地儲存所有標籤”。10. push 元件 *.podspec 檔案
pod repo push Specs AppPod.podspec --allow-warnings
複製程式碼
推送時,如果一直報錯,修護了Error還是一直報同樣的Error,這時可以執行下pod cache clean --all
清空快取。
11. 不同configurations設定巨集
當新增一個Ad-hoc的configuration,這個也需要設定DEBUG這個巨集,並且在元件中也用到了DEBUG的巨集定義,那麼需要對所有的元件進行DEBUG的設定。方法如下
#設定Debug引數
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if config.name == 'Debug'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) DEBUG=1'
end
if config.name == 'Ad-hoc'
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] = '$(inherited) DEBUG=1'
end
end
end
end
#設定引數完成
複製程式碼
12. 更新OpenSSL失敗
OpenSSL更新失敗,可以刪除/tmp/openssl 資料夾,重新嘗試。
13. OpenSSL 的使用
在使用支付寶SDK時,會有引入OpenSSL資料夾,其中檔案中使用#include <openssl/e_os2.h>
。將SDK放入元件中,會報錯,提示找不到檔案。
解決方法: 在*.podspec檔案中 新增 ss.header_dir = "openssl"
用來新增標頭檔案夾openssl。
14. ARC 和 MRC 相容
將使用MAC的放入subspec
s.subspec 'JTObjectMapping' do |ss|
ss.source_files = 'StoreBase/Classes/JTObjectMapping/*.{h,m}'
ss.public_header_files = 'StoreBase/Classes/JTObjectMapping/*.h'
ss.requires_arc = false
end
複製程式碼
因為JTObjectMapping第三方庫使用的MRC所以特殊宣告ss.requires_arc = false
. 在主spec中使用的ARC,則宣告ss.requires_arc = true
.
此時主spec是ARC而JTObjectMapping是MRC,對JTObjectMapping中的檔案都會新增一個-fno-objc-arc的編譯巨集。
15. 基礎元件的版本更新
當主工程釋出了版本,那麼依賴的基礎元件版本也固定,不能再做修改。當需要對基礎元件進行修改,那麼版本需要更新,版本號加一。 當某個基礎元件A的版本號修改,那麼依賴這個元件的所有元件BCD也都要修改版本。然後依賴BCD的元件EFG也要修改版本號,以此類推
16. 釋出版本修改
釋出版本修改: 基礎元件,將基礎元件的所有依賴修改為大版本(如“=1.1.0”格式),必須指定版本號。比如有一個元件的版本號是1.0.5,那麼這個版本進行了1.0.1到1.0.5的開發,在提交版本的需要修改1.1.0版本,並執行1.1.0版本。為了,(1)方便線上版本可以指定具體的版本。 (2)方便下一個版本的開發。 殼工程中,pod file檔案的修改,將業務元件制定dev分支,修改為制定版本號,必須指定版本號。
業務元件的使用: 開發時,podfile中直接dev分支獲取程式碼,並在dev上進行開發。 等需要釋出版本進行冒煙測試時,修改podfile為制定版本號。如“=1.1.0”。
pod 'Location', :git => 'git@code.xxx.com:ios/Location.git', :branch => 'dev'
複製程式碼
基礎元件的使用 在每個基礎元件中,使用“~>1.0.3”進行開發,並在每次修改的時候,新增版本號。 基礎元件依賴其他元件的時候,也修改為“~>1.0.3”, 那麼在pod install的時候,就可以更新到最新的版本,不需要清理快取。 釋出版本的時候,在每一個元件中,指定版本號。如“=1.1.0”。儲存每個釋出的正式版本,都可以明確的知道所有元件的版本號。 釋出版本後進行開發,那麼需要修改依賴版本後“~>1.1.0”,不需要清理快取,方便開發。 開發時,版本號的修改,僅僅針對需要修改的版本號。其他版本號保持不變。
圖片資源 建立一個圖片資源的pod, 使用s.resources的方式進行新增圖片。那麼在xib中或imageNamed:"""直接可進行訪問。不需要進行bundle的控制。???
未完待續 // END