iOS 元件化 使用cocoapods整合實戰演練
之前寫過一篇iOS 元件化實現的一些思路總結
,這篇作為續集,聊一聊使用Cocoapods
在iOS平臺元件化的實現和整合。
結果
本文中的兩個例子可以在YTThirdPlatformManager 專案中找到。
工具介紹
Cocoapods
是iOS/osx平臺的開發庫管理工具,簡單的配置然後執行安裝命令Cocoapods
會自動去下載第三方庫並且做好相應的配置,簡化了引入第三方庫的流程,讓開發更簡單高效,是iOS開發的必備工具,使用Cocoapods
作為元件化的工具是一個不錯的選擇。
安裝和設定
安裝和設計可以參考這篇文章:Cocopods安裝和升級備忘錄
實現
簡單專案元件化
以一個測試模組解耦的場景實現簡單專案的元件化,主要包含以下內容
- Pod庫專案建立
- 最基礎podspec檔案的編寫的解釋
- 客戶端整合
建立專案
使用pod lib create
建立專案,會遇到幾個需要輸入的地方,具體的解釋看程式碼段中的註釋
➜DevPods pod lib create PTTestKit Cloning `https://github.com/CocoaPods/pod-template.git` into `PTTestKit`. Configuring PTTestKit template. ------------------------------ To get you started we need to ask a few questions, this should only take a minute. If this is your first time we recommend running through with the guide: - http://guides.cocoapods.org/making/using-pod-lib-create.html ( hold cmd and double click links to open in a browser. ) # 使用的語言 What language do you want to use?? [ Swift / ObjC ] > Objc # 是否包好測試工程,指定YES用於模組化的解耦測試 Would you like to include a demo application with your library? [ Yes / No ] > yes # 整合的測試模組,不需要指定None Which testing frameworks will you use? [ Specta / Kiwi / None ] > None # UI測試模組,不需要指定No Would you like to do view based testing? [ Yes / No ] > No # 指定類字首 What is your class prefix? > PT Running pod install on your new library. 複製程式碼
podspec 檔案編寫
一個簡單的 podspec 檔案如下,具體欄位的解釋檢視程式碼中的註釋即可
Pod::Spec.new do |s| s.name= 'PTTestKit' s.version= '0.1.0' s.summary= 'Wow PTTestKit.' # This description is used to generate tags and improve search results. #* Think: What does it do? Why did you write it? What is the focus? #* Try to keep it short, snappy and to the point. #* Write the description between the DESC delimiters below. #* Finally, don't worry about the indent, CocoaPods strips it! # 長的描述資訊 s.description= <<-DESC Wow this is a amazing kit, Enjoy yourself! DESC # 提交到git服務區的專案主頁,沒提交可以指定任意值,但需要保留這一項,否則會報錯 # attributes: Missing required attribute `homepage`. s.homepage= 'https://github.com/flypigrmvb/PTTestKit' # s.screenshots= 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' # 授權檔案 s.license= { :type => 'MIT', :file => 'LICENSE' } # 使用者資訊 s.author= { 'flypigrmvb' => '[email protected]' } # 提交到git上的原始碼路徑,沒提交可以指定任意值,但需要保留這一項,否則會報錯 # attributes: Missing required attribute `source`. s.source= { :git => 'https://github.com/flypigrmvb/PTTestKit.git', :tag => s.version.to_s } # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>' # 指定最低的ios版本 s.ios.deployment_target = '8.0' # 原始檔的路徑 s.source_files = 'PTTestKit/Classes/**/*' # 公共的標頭檔案,按需設定 s.public_header_files = 'PTTestKit/Classes/Public/**/*.h' # 私有的標頭檔案,按需設定 s.private_header_files = 'PTTestKit/Classes/Private/**/*.h' # 依賴的系統Framework,按需設定 # s.frameworks = 'UIKit', 'MapKit' # 依賴其他的pod庫,按需設定 # s.dependency 'AFNetworking', '~> 2.3' end 複製程式碼
客戶端整合
如果在建立Pod庫專案的步驟集成了 Example 測試專案,在測試專案下的podfile預設包含了當前的Pod庫專案
#use_frameworks! target 'PTTestKit_Example' do pod 'PTTestKit', :path => '../' target 'PTTestKit_Tests' do inherit! :search_paths end end 複製程式碼
切換到測試專案目錄下,執行pod install
命令,完了之後測試專案集成了Pod專案。下面是在測試專案中使用Pod庫專案中一些功能的簡單例z
#import "PTViewController.h" #import <PTTestKit/PublicFile.h> // !!private header 可以匯入 #import <PTTestKit/PrivateFile.h> // !!報錯 //#import <PTTestKit/ProjectFile.h> @interface PTViewController () @end @implementation PTViewController - (void)viewDidLoad { [super viewDidLoad]; [self addActionWithName:@"Test" callback:^{ NSLog(@"===="); }]; [self addActionWithName:@"PrivateFile" callback:^{ [PrivateFile test]; }]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [PrivateFile test]; } @end 複製程式碼
分模組元件化
以一個第三發元件整合的場景為例,實現分模組元件化,主要包含以下內容:
- 建立核心模組
- 建立子模組
- 客戶端整合
pod庫專案的建立流程和簡單模組元件步驟一致,不在贅述
podspec 檔案編寫
該檔案建立了一個Core模組,用於存放抽象的介面、基類以及一些公用的工具類和標頭檔案,以及幾個子模組用於具體的第三方平臺的實現。具體的內容可以檢視以下程式碼中的註釋內容
Pod::Spec.new do |s| s.name= 'PTThirdPlatformKit' s.version= '0.1.0' s.summary= 'A short description of PTThirdPlatformKit.' # This description is used to generate tags and improve search results. #* Think: What does it do? Why did you write it? What is the focus? #* Try to keep it short, snappy and to the point. #* Write the description between the DESC delimiters below. #* Finally, don't worry about the indent, CocoaPods strips it! s.description= <<-DESC TODO: Add long description of the pod here. DESC s.homepage= 'https://github.com/flypigrmvb/PTThirdPlatformKit' # s.screenshots= 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' s.license= { :type => 'MIT', :file => 'LICENSE' } s.author= { 'flypigrmvb' => '[email protected]' } s.source= { :git => 'https://github.com/flypigrmvb/PTThirdPlatformKit.git', :tag => s.version.to_s } # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>' s.ios.deployment_target = '8.0' # 設定預設的模組,如果在pod檔案中匯入pod專案沒有指定子模組,匯入的是這裡指定的模組 s.default_subspec = 'Core' # 定義一個核心模組,使用者存放抽象的介面、基類以及一些公用的工具類和標頭檔案 s.subspec 'Core' do |subspec| # 原始碼 subspec.source_files = 'PTThirdPlatformKit/Classes/**/*' # 配置系統Framework subspec.frameworks = 'CoreMotion' subspec.dependency 'SDWebImage' # 新增依賴的系統靜態庫 subspec.libraries = 'xml2', 'z', 'c++', 'stdc++.6', 'sqlite3' end # 支付寶模組 s.subspec 'AlipayManager' do |subspec| # 原始碼 subspec.source_files = 'PTThirdPlatformKit/AlipayManager/**/*' # 新增資原始檔 subspec.resource = 'PTThirdPlatformKit/AlipayManager/**/*.bundle' # 新增依賴第三方的framework subspec.vendored_frameworks = 'PTThirdPlatformKit/AlipayManager/**/*.framework' # 新增依賴系統的framework subspec.frameworks = 'CoreTelephony', 'SystemConfiguration' # 依賴的核心模組 subspec.dependency 'PTThirdPlatformKit/Core' end # QQ模組 s.subspec 'TencentManager' do |subspec| # 原始碼 subspec.source_files = 'PTThirdPlatformKit/TencentManager/**/*' # 新增資原始檔 subspec.resource = 'PTThirdPlatformKit/TencentManager/**/*.bundle' # 新增依賴第三方的framework subspec.vendored_frameworks = 'PTThirdPlatformKit/TencentManager/**/*.framework' # 新增依賴系統的framework subspec.frameworks = 'SystemConfiguration' # 依賴的核心模組 subspec.dependency 'PTThirdPlatformKit/Core' end # 微博模組 s.subspec 'WeiboManager' do |subspec| # 原始碼 subspec.source_files = 'PTThirdPlatformKit/WeiboManager/**/*' # 依賴的微博pod庫 subspec.dependency 'WeiboSDK' subspec.dependency 'PTThirdPlatformKit/Core' end # 微信模組 s.subspec 'WXManager' do |subspec| # 原始碼 subspec.source_files = 'PTThirdPlatformKit/WXManager/**/*' # 依賴的微信pod庫 subspec.dependency 'WechatOpenSDK' subspec.dependency 'PTThirdPlatformKit/Core' end end 複製程式碼
客戶端整合
podfile檔案如下,可以匯入主模組和任意的子模組的組合
#use_frameworks! platform :ios, '8.0' target 'PTThirdPlatformKit_Example' do pod 'PTTestKit', :path => '../../PTTestKit' # 主模組 pod 'PTThirdPlatformKit', :path => '../' # 子模組快 pod 'PTThirdPlatformKit/AlipayManager', :path => '../' pod 'PTThirdPlatformKit/TencentManager', :path => '../' pod 'PTThirdPlatformKit/WeiboManager', :path => '../' pod 'PTThirdPlatformKit/WXManager', :path => '../' end target 'PTThirdPlatformKit_Example_Developer' do pod 'PTTestKit', :path => '../../PTTestKit' pod 'PTThirdPlatformKit', :path => '../' pod 'PTThirdPlatformKit/AlipayManager', :path => '../' pod 'PTThirdPlatformKit/TencentManager', :path => '../' pod 'PTThirdPlatformKit/WeiboManager', :path => '../' pod 'PTThirdPlatformKit/WXManager', :path => '../' end 複製程式碼
遇到問題
開發中的Pod庫依賴另一個Pod庫的處理
參考:guides.cocoapods.org/syntax/pods…
podspec檔案新增新增
s.vendored_frameworks = 'PTDataModule/Frameworks/*.framework' 複製程式碼
ARC環境中配置非ARC檔案
需要用到podspec規則中的subspec和requires_arc
參考:
guides.cocoapods.org/syntax/pods…
guides.cocoapods.org/syntax/pods…s.requires_arc = true # no arc files rules non_arc_files = 'PTDataModule/Classes/**/JSONKit.{h,m}' s.exclude_files = non_arc_files s.subspec 'no-arc' do |sna| sna.requires_arc = false sna.source_files = non_arc_files end 複製程式碼
PrefixHeader
參考:guides.cocoapods.org/syntax/pods…
podspec指定 PTDataModule-prefixheader.pch 檔案
s.prefix_header_file = 'PTDataModule/SupportFiles/PTDataModule-prefixheader.pch' 複製程式碼
PTDataModule-prefixheader.pch 檔案內容
#import "UtilMacro.h" #import "DebugConfig.h" #import "TIMAdapter.h" 複製程式碼
有個坑,使用pod install 之後自定義的pch檔案在專案中找不到了,但是內容會新增到PTDataModule-prefix.pch檔案中
spec.prefix_header_contents = '#import <UIKit/UIKit.h>', '#import <Foundation/Foundation.h>' 複製程式碼
Pod 更新不成功問題
[!] The 'Pods-PTThirdPlatformKit_Example' target has transitive dependencies that include static binaries: (/Users/aron/PuTaoWorkSpace/Plush_devpods_developer/DevPods/PTThirdPlatformKit/Example/Pods/WechatOpenSDK/OpenSDK1.8.0/libWeChatSDK.a and /Users/aron/PuTaoWorkSpace/Plush_devpods_developer/DevPods/PTThirdPlatformKit/Example/Pods/WeiboSDK/libWeiboSDK/libWeiboSDK.a) 複製程式碼
解決辦法:
#use_frameworks! (註釋這個)
新增.a靜態庫和對應的標頭檔案 PTBehaviorStat
s.public_header_files = 'PTBehaviorStat/Classes/**/*.h', 'PTBehaviorStat/vendor/**/*.h' s.vendored_library = 'PTBehaviorStat/**/*.a' 複製程式碼
pod lib create 建立庫拉取GitHub模板資料慢的問題
--template 引數指定本地的 模板資料
Pod開發庫依賴本地開發庫的問題
參考:
stackoverflow.com/questions/1…
比如Pod開發庫A依賴Pod開發庫B,依賴的資訊填寫如下即可,不需要指定路徑獲取其他資訊
s.dependency 'DevLibB' 複製程式碼
在測試工程或者客戶端工程的的podfile檔案中需要顯示的匯入DevLibB,這樣即可
pod 'DevLibB', :path => '../../DevLibB' 複製程式碼
原始檔沒有配置對會找不到
subspec.source_files = 'PTThirdPlatformKit/WeiboManager/**/*' 複製程式碼
如果配置(如下所示)是錯誤的路徑,在客戶端是找不到這個類的,需要檢查原始檔配置的是否正確
subspec.source_files = 'PTThirdPlatformKit/WeiboManager111/**/*' 複製程式碼