背景
之前寫過一篇 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' => '862709539@qq.com' }
# 提交到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' => '862709539@qq.com' }
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檔案中
可以使用這種方式,直接把需要匯入的標頭檔案使用引數的方式指定
參考:
guides.cocoapods.org/syntax/pods…
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/**/*'
複製程式碼
總結
以上是我在使用cocoapods做元件化整合實踐的一些總結和遇到的一些問題,希望對有需要的朋友有幫助。