最近在研究組件化,發(fā)現(xiàn)網(wǎng)上的資料有很多尊浪,很詳細(xì)匣屡,可是看的越多感覺越懵??封救,我現(xiàn)在需要的是盡量簡(jiǎn)單化,于是就有了這一篇實(shí)戰(zhàn)貼捣作,簡(jiǎn)單實(shí)用誉结!
一、簡(jiǎn)介
定義
簡(jiǎn)單來說券躁,組件化
就是將一個(gè)APP
中的代碼進(jìn)行抽取惩坑,分成若干個(gè)項(xiàng)目,然后按照cocoapods
的方式進(jìn)行組織也拜,形成一個(gè)擁有完整業(yè)務(wù)邏輯的工程以舒。也就是說一個(gè)組件就是一個(gè)可以獨(dú)立運(yùn)行的項(xiàng)目。它就是用來解耦
的慢哈,當(dāng)你的APP業(yè)務(wù)越來越龐大的時(shí)候蔓钟,就需要將業(yè)務(wù)隔離
,獨(dú)立開發(fā)
卵贱。
優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 組件的
獨(dú)立性
滥沫,各組件獨(dú)立開發(fā),互不影響艰赞,可以減少提交代碼時(shí)的沖突- 資源重用佣谐,將于業(yè)務(wù)無關(guān)的代碼抽離出來放在一個(gè)基礎(chǔ)組件中
- 高效迭代
- 配合二進(jìn)制,可以加快項(xiàng)目的編譯速度
缺點(diǎn)
- 開發(fā)起來步驟要復(fù)雜些方妖,代碼的抽離也不是很容易
二狭魂、組件的劃分
每一個(gè)組件都是一個(gè)獨(dú)立的pod庫
,我們把組件化的代碼放在Git
上托管党觅,制作成私有pod
,然后通過cocoapods
就可以連接各個(gè)組件雌澄,最后把它們合在一起,變成一個(gè)完整的項(xiàng)目
原則
- 基礎(chǔ)代碼杯瞻;基礎(chǔ)配置(宏定義镐牺、常量)、分類魁莉、網(wǎng)絡(luò)請(qǐng)求睬涧、其它的一些工具類
- 功能代碼;自定義的一些UI控件旗唁;一些功能類畦浓,如音頻處理、斷點(diǎn)續(xù)傳等
- 業(yè)務(wù)代碼检疫;具體的業(yè)務(wù)讶请,如首頁模塊、個(gè)人中心模塊等
三屎媳、組件的創(chuàng)建
pod 的原理
當(dāng)我們執(zhí)行 pod install
把代碼集到項(xiàng)目中夺溢,這個(gè)過程會(huì)發(fā)生一些什么事情论巍?
以AFNetworking
為例,當(dāng)它的源碼提交到Git
上的時(shí)候,里面會(huì)有一個(gè).spec
的文件风响,這個(gè)文件是描述框架信息的嘉汰,比如框架的名稱、版本號(hào)钞诡、真實(shí)源碼地址等郑现。
在Git
上有專門的一個(gè)遠(yuǎn)程倉庫用來存放所有的 .spec
文件,我們執(zhí)行pod install
的時(shí)候荧降,會(huì)先去本地找這個(gè)庫對(duì)應(yīng)的.spec
文件接箫,這個(gè)文件是當(dāng)你在安裝pod
執(zhí)行pod setup
的時(shí)候或者更新pod的時(shí)候,就會(huì)把遠(yuǎn)程倉庫里的.spec
文件拉取到本地朵诫。那如果本地找不到這個(gè)描述文件辛友,那么它就會(huì)去把遠(yuǎn)程倉庫的spec文件拉取到本地,然后再去找剪返,找到了之后废累,就能夠得到描述文件里的真實(shí)源碼地址,通過Git
把它拉取下來
制作一個(gè)私有pod庫(重難點(diǎn))
步驟
首先脱盲,打開終端邑滨,進(jìn)入項(xiàng)目主目錄中
cd ~
cd desktop
mkdir 組件化項(xiàng)目
cd 組件化項(xiàng)目
1. 組件工程(用來發(fā)布的組件,開發(fā)時(shí)用的工程)
- 思路:新建一個(gè)空白工程钱反,在工程中進(jìn)行業(yè)務(wù)代碼的開發(fā)掖看,比如首頁;開發(fā)完畢后將代碼提交到
Git
- 具體步驟
- 碼云上新建一個(gè)私有倉庫(為了代碼安全面哥,搞成私有的哎壳!)
-
clone
到本地,進(jìn)行業(yè)務(wù)代碼的開發(fā)(所有的代碼都放在一個(gè)主目錄文件夾中如ExamComponent
)尚卫,可多人開發(fā)归榕,使用Git
做版本控制 - 開發(fā)完畢后,上到到
Git
上吱涉,把ExamComponent
文件夾拷貝出來
2. 私有pod庫
-
創(chuàng)建
本地pod庫
-
進(jìn)入項(xiàng)目目錄中刹泄,執(zhí)行以下命令
cd 組件化項(xiàng)目 pod lib create CXComponentBasic
這個(gè)是
pod
提供的一個(gè)模板命令,可以創(chuàng)建一個(gè)標(biāo)準(zhǔn)的pod
庫怎爵,我們只需要把拷貝過來的業(yè)務(wù)代碼
放在Classes
文件夾中循签,然后修改.spec
文件,就可以發(fā)布了疙咸,稍候?qū)⒃敿?xì)介紹
-
創(chuàng)建
私有索引庫
通過上面介紹的pod的原理
,我們知道每個(gè)開源庫都對(duì)應(yīng)一個(gè).spec
文件风科,這個(gè).spec
文件默認(rèn)是放在開源的pod索引庫
里的撒轮,別人都可以搜索到乞旦,我們?nèi)绻枰獎(jiǎng)?chuàng)建私有pod庫
,就不能把.spec
文件放在默認(rèn)開源索引庫
里题山,我們需要把它放在自己的私有索引庫
中兰粉。
- 碼云上新建一個(gè)私有庫,用來存放spec文件顶瞳,這個(gè)庫也可稱為索引庫
- 回到終端玖姑,將這個(gè)索引庫關(guān)聯(lián)到本地,命令如下
pod repo add CXGiteePrivateRepo https://git.oschina.net/baiyingqiu/CXGiteePrivateRepo.git
CXGiteePrivateRepo
是私有索引庫的名稱
可通過命令pod repo
可查看本地有哪些索引庫
關(guān)聯(lián)pod庫的遠(yuǎn)程倉庫
前面兩步已經(jīng)把本地pod庫
和私有索引庫
創(chuàng)建好了,下面就不要把pod庫的.spec
文件,上傳到私有索引庫中就行了慨菱。-
關(guān)聯(lián)
本地pod庫
- 碼云上新建一個(gè)私有庫焰络,名稱和
本地pod庫
一樣,用來和它進(jìn)行關(guān)聯(lián),命令如下
git remote add origin https://gitee.com/sunnoryChen/CXComponentBasic.git
- 碼云上新建一個(gè)私有庫焰络,名稱和
修改
.spec
文件
修改版本號(hào)和路徑等-
發(fā)布
- 打開本地私有pod庫的示例項(xiàng)目
cd xx pod install clean
先執(zhí)行下安裝符喝,看看pod庫是否報(bào)錯(cuò)闪彼,如果報(bào)錯(cuò)說明你的業(yè)務(wù)代碼有問題沪饺,得改燕侠!
-
返回上一級(jí)目錄
確保你的業(yè)務(wù)代碼正常后,就可以返回到上級(jí)目錄橘券,準(zhǔn)備發(fā)布啦- 關(guān)聯(lián)遠(yuǎn)程倉庫
git remote add origin https://gitee.com/sunnoryChen/CXComponentBasic.git
git remote -v 可查看關(guān)聯(lián)了哪些遠(yuǎn)程倉庫
- 上傳到遠(yuǎn)程倉庫
git add . git commit -m “0.1.2” git tag 0.1.2 git push origin master --tags -f
注意 tag 值需要和pod的版本號(hào)保持一致
- 驗(yàn)證
.spec
文件是否可用
pod spec lint --sources='https://gitee.com/sunnoryChen/CXGiteePrivateRepo.git,https://github.com/CocoaPods/Specs' --allow-warnings
這兩個(gè)路徑一個(gè)是我們的私有索引庫地址茉稠,一個(gè)是pod的公共索引庫地址
- 發(fā)布到私有索引庫中
驗(yàn)證通過后描馅,驗(yàn)證不通過,那就看哪報(bào)錯(cuò)就改哪兒吧而线,反正有不少坑的??
發(fā)布的命令如下:
pod repo push CXGiteePrivateRepo CXComponentBasic.podspec --sources='https://gitee.com/sunnoryChen/CXGiteePrivateRepo.git,https://github.com/CocoaPods/Specs' --allow-warnings
CXGiteePrivateRepo
是我們之前創(chuàng)建的本地索引庫名
CXComponentBasic.podspec
就是我們要發(fā)布庫的索引庫
3. 組件的使用
修改 podfile 文件铭污,如下
# 使用私人pod庫的需要在Podflie中添加這句話,指明你的版本庫地址
source 'https://gitee.com/sunnoryChen/CXGiteePrivateRepo.git'
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, ‘8.0’
pod 'CXComponentBasic', '~> 0.1.2'
Tips
- 組件項(xiàng)目中怎么使用 .pch 預(yù)編譯文件
找到pod的目錄 “Support Files - RDZJComponentLogin-prefix.pch” ,這個(gè)相當(dāng)于實(shí)際項(xiàng)目中的pch文件吞获,防止一些預(yù)編譯的命令况凉,可全局調(diào)用的
- 組件內(nèi)怎么分層級(jí)的
修改 .spec
文件
#頭文件
s.public_header_files = 'Pod/Classes/Category/UIKit/CXUIKit.h'
s.subspec 'Category' do |vdr|
vdr.subspec 'Foundation' do |vd|
vd.source_files = "CXComponentPublic/Classes/Category/Foundation/**/*"
end
vdr.subspec 'UIKit' do |vd|
vd.source_files = "CXComponentPublic/Classes/Category/UIKit/**/*"
end
end
-
組件怎么依賴三方庫
s.dependency 'MBProgressHUD', '~> 1.0.0'
-
組件怎么使用自己活三方的 framework 或者 .a 文件
s.ios.vendored_frameworks = "xxx//.framework"
s.ios.vendored_libraries = "xxx//.a” 組件內(nèi)部相互依賴?
s.subspec 'BaseClass' do |bsc|
bsc.source_files = "TestPod/Classes/BaseClass/*"
# 字庫BaseClass中用到了字庫Controls中的東西各拷,需要添加依賴
bsc.dependency "TestPod/Controls"
end
TestPod
是你的組件名刁绒,這個(gè)命令的意思是TestPod
組件里的BaseClass
子庫依賴了 的TestPod
組件中的Controls
子庫
- 組件中怎么使用
資源文件
比如圖片
、Xib
烤黍、txt文檔
,因?yàn)榻M件中圖片不是放在默認(rèn)Main Bundle
中的知市,所以是不能使用ImageNamed
方法獲取圖片的,需要知道當(dāng)前圖片所在的Bundle
, 例如
圖片
+ (instancetype)cx_imagePathWithName:(NSString *)imageName bundle:(NSString *)bundle targetClass:(Class)targetClass {
NSInteger scale = [[UIScreen mainScreen] scale];
NSBundle *currentBundle = [NSBundle bundleForClass:targetClass];
NSString *name = [NSString stringWithFormat:@"%@@%zdx",imageName,scale];
NSString *dir = [NSString stringWithFormat:@"%@.bundle",bundle];
NSString *path = [currentBundle pathForResource:name ofType:@"png" inDirectory:dir];
return path ? [UIImage imageWithContentsOfFile:path] : nil;
}
Xib
+ (instancetype)base_mainView {
NSBundle *currentBundle = [NSBundle bundleForClass:[self class]];
CXBaseXibView *view = (CXBaseXibView *)[currentBundle loadNibNamed:@"CXBaseXibView" owner:nil options:nil].lastObject;
view.frame = CGRectMake(0, 0, UIScreen.mainScreen.bounds.size.width, 128);
return view;
}
txt
NSBundle *currentBundle = [NSBundle bundleForClass:[self class]];
NSLog(@"text_currentBundle = %@",currentBundle);
NSString *dir = [NSString stringWithFormat:@"%@.bundle",@"RDZJComponentLogin"];
NSString *plistPath = [currentBundle pathForResource:@"userDeal" ofType:@"txt" inDirectory:dir];
NSLog(@"plistPath = %@",plistPath);
Questions
-
pod
發(fā)布命令不可用
需要先注冊(cè)
一下pod
才能有發(fā)布庫的權(quán)限 eg.
pod trunk register 2235037295@qq.com "georry"
- 發(fā)布庫時(shí)速蕊,報(bào) Swift 版本錯(cuò)誤
在 podspec中添加 s.swift_version = '4.0'
- 更新私有庫版本時(shí),出現(xiàn)
[!] The repo MySpecs at ../../../../.cocoapods/repos/MySpecsis not clean
需要更新一下我們的索引庫
執(zhí)行命令pod repo update
本地私有索引庫名稱(MySpecs)
執(zhí)行命令 pod repo update 本地私有索引庫名稱(MySpecs)
- 在組件內(nèi)部使用三方庫時(shí)嫂丙,要這樣導(dǎo)入
Masonry/Masonry.h
- OC、Swift 混編包规哲,怎么做組件
不使用8 !!
四隅肥、組件的通訊
采用 CTmediator
的路由解決方案竿奏,將需要暴露的接口放在它的分類方法中,具體使用方法可參考上篇文章