概況
眾所周知組件化是個(gè)好東西笛园,它把項(xiàng)目拆分成多個(gè)模塊,讓每個(gè)模塊能夠獨(dú)立出來(lái)解除各個(gè)模塊之間的耦合性侍芝,作為每個(gè)獨(dú)立的模塊不僅僅能夠使用組合的方式去組建各個(gè)不同的功能組合(前提是各個(gè)組件劃分的顆粒度只要足夠醒忻),而且能夠獨(dú)立出來(lái)運(yùn)行州叠,在開(kāi)發(fā)運(yùn)行以及測(cè)試中極大的提升了開(kāi)發(fā)效率棵红,讓整個(gè)項(xiàng)目在維護(hù)上變得方便,而且整個(gè)項(xiàng)目的擴(kuò)展性變得更健壯咧栗。
在 iOS
中可以通過(guò) Pods
管理各個(gè)組件逆甜,Pods
的原理不做介紹,重點(diǎn)說(shuō)在制作組件的方法與實(shí)踐致板。
相信大部分項(xiàng)目在創(chuàng)建的時(shí)候交煞,可能都沒(méi)有將組件化的工程架構(gòu)放入其中,因?yàn)槠鸪醯捻?xiàng)目可能并不大斟或,用簡(jiǎn)單的多人協(xié)作開(kāi)發(fā)模式加上代碼架構(gòu)模式(如 MVC/MVVM/MVP
等)進(jìn)行項(xiàng)目的開(kāi)發(fā)素征,這樣速度快,開(kāi)發(fā)周期短萝挤,更符合敏捷開(kāi)發(fā)的原則御毅,所以一開(kāi)始可能并沒(méi)過(guò)多的去考慮組件化。但是隨著項(xiàng)目的不斷壯大怜珍,項(xiàng)目中不斷加入新的功能端蛆,慢慢的就會(huì)發(fā)現(xiàn)項(xiàng)目的編譯時(shí)間越來(lái)越長(zhǎng),各個(gè)功能的耦合性也變得越來(lái)越高酥泛,最為頭疼的是今豆,假如有需求要求某個(gè)功能模塊抽出來(lái)單獨(dú)的去集成到公司的另一個(gè)產(chǎn)品中嫌拣,由于一開(kāi)始的項(xiàng)目架構(gòu)設(shè)計(jì)造成的代碼的關(guān)聯(lián)耦合,根本無(wú)法進(jìn)行模塊化的抽出晚凿,是不是得崩潰到哭亭罪。每一次痛苦的歷程總會(huì)沖擊出新的解決方案,于是組件化的搭建開(kāi)始了歼秽。
使用 Pods
搭建組件的背景分兩種:
1.正在開(kāi)發(fā)的項(xiàng)目轉(zhuǎn)變成組件
2.空白項(xiàng)目应役,從0到1構(gòu)建組件
對(duì)于第一種,老項(xiàng)目遷移成組件架構(gòu)模式燥筷,可以分成三步:
1.重構(gòu)項(xiàng)目箩祥,分離出各個(gè)模塊,劃分清楚組件構(gòu)件(可以通過(guò)使用路由思想完成組件通信的解耦)
2.抽出組件分離出主項(xiàng)目肆氓,將組件制作成Pods
管理的私有庫(kù)袍祖,并發(fā)布模塊組件版本
3.主項(xiàng)目使用Pods
進(jìn)行各個(gè)組件的集成
第二種就相對(duì)簡(jiǎn)單點(diǎn)了,省去了第一種的第一步(這是個(gè)耗時(shí)耗力的過(guò)程)谢揪,直接在創(chuàng)建整個(gè)項(xiàng)目的時(shí)候構(gòu)建出各個(gè)組件蕉陋,于是就變成了兩步:
1.將組件制作成
Pods
管理的私有庫(kù),并發(fā)布模塊組件版本
2.主項(xiàng)目使用Pods
進(jìn)行各個(gè)組件的集成
由于 Pods
在創(chuàng)建私有庫(kù)的管理時(shí)候需要綁定git
實(shí)現(xiàn)創(chuàng)建拨扶,所以整個(gè)項(xiàng)目需要依托于 git 管理凳鬓。以下的搭建是在當(dāng)前項(xiàng)目處于 git
管理中的操作。由于 github
創(chuàng)建私有庫(kù)需要 money患民,所以這里我選用了其他的git
托管缩举,有很多代碼托管網(wǎng)站可以使用,我用的是 Coding
匹颤。
搭建簡(jiǎn)述
Pods
的搭建組件步驟如下:
1.本地創(chuàng)建私有的
repo
倉(cāng)庫(kù)(需要與遠(yuǎn)程git
托管地址綁定)
2.創(chuàng)建并配置當(dāng)前的pod
的.spec
文件
3.驗(yàn)證當(dāng)前的.spec
的有效性
4.發(fā)布當(dāng)前的pod
版本(默認(rèn)會(huì)推送到遠(yuǎn)端)
搭建詳情
- 本地創(chuàng)建私有的
repo
倉(cāng)庫(kù)
打開(kāi)term
控制臺(tái)仅孩,通過(guò)執(zhí)行如下命令進(jìn)行本地私有的repo
的創(chuàng)建
pod repo add LCProjectSpecs https://git.coding.net/lccdl/LCModulLearnDemo.git
執(zhí)行完成如下:
執(zhí)行命令之后,我們可以打開(kāi)本地的 repo
查看私有的庫(kù)是否創(chuàng)建成功印蓖,使用如下命令:
cd ~/.cocoapods/repos
結(jié)果如下:
- 創(chuàng)建并配置當(dāng)前的
pod
的.spec
文件
在創(chuàng)建私有的pod
之前我們需要進(jìn)入當(dāng)前的模塊所在的文件夾辽慕,然后執(zhí)行如下命令進(jìn)行.sepc
文件的創(chuàng)建
pod spec create https://git.coding.net/lccdl/LCModulLearnDemo.git
執(zhí)行完成之后,當(dāng)前目錄下會(huì)出現(xiàn)一個(gè).spec 文件另伍,用編輯工具打開(kāi)它鼻百,它是一個(gè)ruby
格式的文件配置可以按照如 下進(jìn)行配置
Pod::Spec.new do |s|
s.name = "LCModulOne" #當(dāng)前的 pod 名字
s.version = "0.1.2" #pod版本
s.summary = "測(cè)試" #描述
s.description = <<-DESC
模塊化開(kāi)發(fā)
DESC
s.homepage = "https://coding.net/u/lccdl/p/LCModulLearnDemo"
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = { "lccdl" => "lcc_dl@163.com" }
s.platform = :ios, "8.0"
s.source = { :git => "https://git.coding.net/lccdl/LCModulLearnDemo.git", :tag => s.version.to_s }
s.source_files = "LCModulOne/LCModulOne/Classes/*"
end
- 驗(yàn)證
specs
的配置是否正確
這里可以通過(guò)兩個(gè)命令來(lái)進(jìn)行驗(yàn)證,兩個(gè)命令分別針對(duì)本地與遠(yuǎn)端的驗(yàn)證
pod lib lint #驗(yàn)證本地 pod 配置是否正確
pod spec lint #驗(yàn)證遠(yuǎn)端 pod 配置是否正確
這里有一個(gè)坑點(diǎn)摆尝,就是可能在本地驗(yàn)證 pod lib lint
的時(shí)候一點(diǎn)問(wèn)題沒(méi)有,但是在進(jìn)行遠(yuǎn)程 pod spec lint
驗(yàn)證的時(shí)候會(huì)出現(xiàn)如下的錯(cuò)誤提示:
這個(gè)問(wèn)題可能是source_files
對(duì)應(yīng)的遠(yuǎn)程的路徑?jīng)]有填寫(xiě)正確造成的因悲,本地驗(yàn)證的時(shí)候堕汞,source_files
對(duì)應(yīng)的路徑的起始路徑是當(dāng)前路徑,而source_files
在遠(yuǎn)程驗(yàn)證時(shí)對(duì)應(yīng)的目錄的根目錄是 git
的根目錄(不是當(dāng)前的 spec
文件所在的目錄了)晃琳,所以可能在驗(yàn)證當(dāng)前的遠(yuǎn)程的目錄的時(shí)候可能會(huì)出現(xiàn)問(wèn)題讯检,只要把目錄的路徑寫(xiě)對(duì)就好了琐鲁。
- 發(fā)布
pod
管理的組件版本
驗(yàn)證成功之后,可以通過(guò)以下命令進(jìn)行當(dāng)前版本的發(fā)布人灼。
pod repo push LCModulDemoSpecs LCModulOne.podspec #LCModulDemoSpecs 是本地的私有庫(kù) LCModulOne.podspec 當(dāng)前的管理模塊的 pod
當(dāng)驗(yàn)證 pod
配置文件沒(méi)有問(wèn)題之后围段,會(huì)將當(dāng)前 pod
發(fā)布到當(dāng)前的私有庫(kù)LCModulDemoSpecs
中,同時(shí)此時(shí)會(huì)默認(rèn)推送到 git
的master
分支中(無(wú)論當(dāng)前處于哪個(gè)分支下投放,都會(huì)推送到主分支)奈泪。這一步完成之后,我們就可以通過(guò)搜索 pods
來(lái)進(jìn)行正常的 pod
的模塊依賴(lài)了灸芳。
- 組合不同的模塊進(jìn)行不同模塊的開(kāi)發(fā)
一旦發(fā)布各自的模塊版本之后涝桅,那么參與項(xiàng)目的其他的人就可以通過(guò)pod
來(lái)加載不同的模塊功能進(jìn)行開(kāi)發(fā)了,不過(guò)因?yàn)槭撬接袔?kù)烙样,所以在進(jìn)行pod
安裝的時(shí)候冯遂,需要指定私有庫(kù)的地址,使用的時(shí)候編輯podfile
谒获,內(nèi)容如下:
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
source '[https://git.coding.net/lccdl/LCModulLearnDemo.git](https://git.coding.net/lccdl/LCModulLearnDemo.git)'
target 'LCMainRootModul' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
# Pods for LCMainRootModul
pod 'LCModulOne'
end
以上說(shuō)的是已有項(xiàng)目的使用 pod 進(jìn)行組件化蛤肌,如果是新開(kāi)發(fā)的某個(gè)模塊需要進(jìn)行 pod 組件化,可以通過(guò) pod 自帶的一個(gè)命令去創(chuàng)建批狱,這樣創(chuàng)建的組件就自帶 Demo 工程以及配置文件了裸准。命令如下:
pod lib create podTestLibrary
創(chuàng)建的時(shí)候會(huì)問(wèn)你幾個(gè)問(wèn)題,直接按需要回答就好了精耐,四個(gè)問(wèn)題如下:
1.是否需要例子工程(建議保留狼速,開(kāi)發(fā)組件的時(shí)候需要用到)
2.根據(jù)需要選擇一個(gè)測(cè)試類(lèi)型
3.是否要基于View
進(jìn)行測(cè)試
4.類(lèi)的前綴
創(chuàng)建完成以后,目錄層級(jí)如下:
開(kāi)發(fā)迭代維護(hù)
在開(kāi)發(fā)組件過(guò)程實(shí)際就是迭代 Pods
庫(kù)的過(guò)程卦停,我們?cè)诿總€(gè)組件的實(shí)例工程中進(jìn)行當(dāng)前的開(kāi)發(fā)向胡,開(kāi)發(fā)完成后通過(guò)發(fā)布組件的版本既可。在開(kāi)發(fā)的時(shí)候由于組件在開(kāi)發(fā)過(guò)程中惊完,所以我們?cè)陂_(kāi)發(fā)自己的組件的時(shí)候僵芹,可以通過(guò)設(shè)置本地路徑的形式去關(guān)聯(lián)正在開(kāi)發(fā)的組件文件,如下:
use_frameworks!
target 'LCModulOne_Example' do
pod 'LCModulOne', :path => '../'
target 'LCModulOne_Tests' do
inherit! :search_paths
end
end
當(dāng)前的工程 update
之后小槐,例子工程中就有了正在開(kāi)發(fā)的pod
了拇派,如下所示:
這里要注意,每次在往開(kāi)發(fā)的 Pods
中添加文件的之后都需要通過(guò) pod update
命令更新本地的正在開(kāi)發(fā)的 Pods
, 否則實(shí)例工程中可能出現(xiàn)找不到當(dāng)前的文件凿跳。
在利用 pod
進(jìn)行組件化的遷移過(guò)程中件豌,由于在進(jìn)行組件發(fā)布的時(shí)候會(huì)默認(rèn)推送到當(dāng)前組件所在的 git
的 master
分支,如果此時(shí) master
分支作為線上發(fā)布版本的分支的話(huà)控嗜,我們是不希望該分支有任何的代碼入侵的茧彤,響應(yīng)的我們可能希望當(dāng)前的pod 發(fā)布只在當(dāng)前的開(kāi)發(fā)環(huán)境分支進(jìn)行,maste
r 不摻雜任何開(kāi)發(fā)過(guò)程中所出現(xiàn)的代碼疆栏,為此曾掂,可以通過(guò)創(chuàng)建兩個(gè) git 的方案去解決這樣的問(wèn)題惫谤,一個(gè) git
作為組件的開(kāi)發(fā)版環(huán)境,另一個(gè) git
專(zhuān)門(mén)作為發(fā)布環(huán)境只進(jìn)行組件的集成與發(fā)布珠洗。如下圖展示:
靈活的組件遷移組合方案
相信在進(jìn)行組件化的工程項(xiàng)目一般都已經(jīng)很龐大了溜歪,如果進(jìn)行全盤(pán)遷移的話(huà),時(shí)間上可能很長(zhǎng)久许蓖,再者伴隨的不定風(fēng)險(xiǎn)或許很大(涉及到項(xiàng)目的重構(gòu))蝴猪,所以結(jié)合之前各自項(xiàng)目的架構(gòu)特點(diǎn)再去聯(lián)合組件化思想對(duì)項(xiàng)目進(jìn)行遷移是明智之舉。組件化的根本目的是解耦項(xiàng)目各個(gè)模塊間的耦合度蛔糯,所以順著這個(gè)思想拯腮,找出項(xiàng)目中耦合度最高的模塊進(jìn)行遷移才是重中之重。
其實(shí)在一般工程在起初創(chuàng)建的時(shí)候都已經(jīng)做到了降低耦合度的構(gòu)建方式蚁飒,例如將一些工具類(lèi)动壤、或者通用的模塊設(shè)計(jì)成項(xiàng)目的底層構(gòu)件服務(wù)于上層模塊,這些底層構(gòu)件不依賴(lài)與上層模塊淮逻,就已經(jīng)做到了很好的降低耦合的目的琼懊,這樣的設(shè)計(jì)有著層級(jí)架構(gòu)
的特點(diǎn),所以通過(guò)層級(jí)架構(gòu)+組件化
構(gòu)建的方式靈活的去降低項(xiàng)目的模塊間的耦合性也是很實(shí)際化的選擇爬早,而且對(duì)比全盤(pán)遷移組件化時(shí)間維度
與可控性
上要占據(jù)更大的優(yōu)勢(shì)哼丈。總之筛严,對(duì)于不同的項(xiàng)目要合理的利用當(dāng)前項(xiàng)目架構(gòu)特點(diǎn)再去與組件化思想相結(jié)合來(lái)進(jìn)行才是靈活變通的根本醉旦。
組件化Pods
構(gòu)想
一旦使用了 pod
構(gòu)建自己的組件之后,會(huì)發(fā)現(xiàn)真的停不下來(lái)桨啃,正式因?yàn)榻M件化的構(gòu)建思想车胡,就會(huì)很自然的想到利用 Pods
去將自己工程中通用的模塊做成一個(gè)組件,然后通過(guò) git
進(jìn)行管理照瘾,一旦去接受一個(gè)新的項(xiàng)目的時(shí)候匈棘,完全可以通過(guò)pod
將需要的不同模塊的東西引入到新的項(xiàng)目中(例如網(wǎng)絡(luò)庫(kù)的封裝、基本工具類(lèi)的封裝析命、常用的宏腳本
)主卫,開(kāi)發(fā)效率也就得到了大大的提高,而且體現(xiàn)了一種前期積累后期建樓的生活哲理不是鹃愤。
參考資料:
http://www.cocoachina.com/ios/20150228/11206.html
http://blog.wtlucky.com/blog/2015/02/26/create-private-podspec/
https://www.cnblogs.com/oc-bowen/p/5885476.html
https://www.zybuluo.com/qidiandasheng/note/392639