iOS-底層原理 35:組件化(一)方案

iOS 底層原理 文章匯總

本文主要講解組件化的兩種方案

組件化

組件化其實就是將模塊單獨抽離、分層,并指定模塊間的通訊方式,從而實現解耦的一種方式,主要運用與團隊開發

為什么需要組件化?

主要有以下四個原因

  • 1、模塊間解耦

  • 2、模塊重用

  • 3、提高團隊協作開發效率

  • 4、單元測試

當項目因為各種需求,越來越來時,如果此時的各個模塊之間是互相調用,即你中有我,我中有你這種情況時,會造成高耦合的情況。一旦我們需要對某一塊代碼進行修改時,就會牽一發而動全身,導致項目難以維護

其問題主要體現在以下幾個方面:

  • 1、修改某個功能時,同時需要修改其他模塊的代碼,因為在其他模塊中有該模塊的引用。可以理解為高耦合導致代碼修改困難

  • 2、模塊對外接口不明確,甚至暴露了本不該暴露的私有接口,修改時費時費力。可以理解為接口不固定導致的接口混亂

  • 3、高耦合代碼產生的后果就是會影響團隊其他成員的開發,產生代碼沖突

  • 4、當模塊需要重用到其他項目時,難以單獨抽離

  • 5、模塊間耦合的忌口導致接口和依賴關系混亂,無法進行單元測試

所以為了解決以上問題,我們需要采用更規范的方式來降低模塊間的耦合度,這就是組件化,也可以理解為模塊化

但是,這里還需要說明一點,因為組件化也是需要一定成本的,需要花費時間設計接口、分離代碼等,所以并不是所有的項目都需要組件化。如果你的項目有以下這些特征就不需要組件化

  • 1、項目較小,模塊間交互簡單,耦合少

  • 2、項目沒有被多個外部模塊引用,只是一個單獨的小模塊

  • 3、模塊不需要重用,代碼也很少被修改

  • 4、團隊規模很小

  • 5、不需要編寫單元測試

如果你的有以下特性,說明你就必須要考慮進行組件化了:

  • 1、模塊邏輯復雜,多個模塊之間頻繁互相引用

  • 2、項目規模逐漸變大,修改代碼變的越來越困難(這里可以理解為:修改一處代碼,需要同時修改其他多個地方)

  • 3、團隊人數變多,提交的代碼經常和其他成員沖突

  • 4、項目編譯耗時較大

  • 5、模塊的單元測試經常由于其他模塊的修改而失敗

組件化方案

組件化方案的8條指標

一個項目經過組件化后如何來評判,主要有以下幾個標準

  • 1、模塊之間沒有耦合,模塊內部的修改不會應該其他模塊
  • 2、模塊可以單獨編譯
  • 3、模塊間數據傳遞明確
  • 4、模塊可以隨時被另一個提供了相同功能的模塊替換
  • 5、模塊對外接口清晰且易維護
  • 6、當模塊接口改變時,此模塊的外部代碼能夠被高效重構
  • 7、盡量用最少的修改和代碼,讓現有的項目實現模塊化
  • 8、支持OC和Swift,以及混編

前4條主要用于衡量一個模塊是否真正解耦,后4條主要用于衡量在項目中實踐中的易用程度

組件化原則
一個項目主要分為3層:業務層通用層以及基礎層,在進行組件化時,有以下幾點說明

組件化圖示

  • 只能上層對依賴,不能下層對上層的依賴,因為下層是對上層的抽象

  • 項目公共代碼資源下沉

  • 橫向的依賴盡量少有,最好下層至通用模塊,或者基礎模塊

組件化方案
常用的組件化方案主要有兩種:

  • 本地組件化:主要是通過在工程中創建library,利用cocoapodsworkspec進行本地管理,不需要將項目上傳git,而是直接在本項目中以framework的方法進行調用

  • cocoapods組件化:主要是利用cocoapods來進行模塊的遠程管理,需要將項目上傳git(需要注意:這里的組件化模塊分為公有庫私有庫,對公司而言,一般是私有庫)

本地組件化

1、創建主工程

  • 首先創建一個工程


    工程結構
  • 集成cocopods,進行本地管理:

$ cd 項目目錄
$ pod init
  • 編輯podfile,并執行pod install

2、創建組件

假設有以下幾個模塊:

  • 主工程:承載主要的表層業務代碼
  • Core:獨立存在,應用加密、接口請求等敏感代碼
  • Base:基類封裝,拓展,基本的數據處理
  • Service:服務層,封裝業務工具類,例如網絡層服務、持久化服務等
  • Pods:三方依賴

其中,各個模塊間的關系如下所示


模塊間關系

下面,我們來進行模塊的創建,以Core模塊為例:

  • 選擇new -> project -> iOS -> Framework,新建一個模塊

    創建library

  • 選擇正確的GroupWorkSpace(這里需要注意一點:創建的library最好放在主工程根目錄下,否則后續podfile執行pod install時會報錯)

    library與工程關聯

  • 將創建的libraryBuild Settings -> Mach-O Type修改為靜態庫 Static Library

    修改配置

3、主工程調用library

  • 在CJLCore中新建一個文件,并添加如下代碼
//類需要聲明為public
public class CJLCoreSetting: NSObject {
    //屬性需要聲明為public
    public static let SCRET_KEY = "SCRET_KEY"
}
  • Build Phases -> Headers -> Public中將新建的文件添加為public,這樣主工程才能訪問該文件

    修改配置2

  • 在主工程中,選擇target -> Linked Frameworks Library中添加CJLCore,只需要build主工程,library能夠自動聯編

    導入

4、使用

首先import CJLCore,然后使用

使用

這里需要注意的是,子library之間的互相調用,與主工程調用library類似,主需要添加依賴、暴露header即可

5、使用cocoapods管理三方依賴

假設我們需要在CJLCore中封裝網絡層代碼,需要用到三方庫Alamofire,在podfile中

platform :ios, '9.0'
inhibit_all_warnings!
use_frameworks!

#配置workspace路徑
workspace 'Modularization.xcworkspace'

################# 三方依賴
# 公有
def workspace_pods
  pod 'SwiftyJSON'
end

# 主工程
def project_only_pods
  pod 'SnapKit'
end

#網絡
def network_layer_pods
  pod 'Alamofire'
end

################# 模塊
target 'CJLCore' do
  #配置libray路徑
  project 'CJLCore/CJLCore.xcodeproj'
  
  workspace_pods
  network_layer_pods

end

################# 主工程
target 'Modularization' do
  
  workspace_pods
  project_only_pods
  network_layer_pods

  target 'ModularizationTests' do
    inherit! :search_paths

  end

  target 'ModularizationUITests' do

  end

end

到此,一個本地組件化的模塊就配置完成了

cocoapods組件化

除了本地組件化,還可以使用cocoapods,其原理如下圖所示

cocoapods組件化流程

這里還是以本地組件化中的結構為例

1、創建私有倉庫

  • 在github上創建一個MySpecs倉庫
    具體步驟:登錄github-->點擊右上角“+”-->選擇 new repository-->輸入Repository name為MySpecs,選擇倉庫類型為 private,點擊Create repository。

  • 將私有倉庫添加至本地~/.cocoapods/repos目錄

pod repo add mySpecs https://github.com/xxx/MySpecs.git

2、創建pods 工程,即組件化工程

  • 使用終端創建CJLServices模塊
pod lib create CJLServices
  • 根據提示依次輸入:ios、swift、yes、none、no、CJL


    創建-1
  • 進入模塊的目錄,將文件拷貝至CJLServices -> Classes

    粘貼文件

  • 執行pod install,會將Classes更新至pods中

    執行結果

3、配置pods工程

修改模塊的配置文件,即CJLServices.podspec

  • 如果需要依賴三方庫,需要配置s.dependency
s.dependency 'AFNetworking'
  • 如果模塊間需要相互引用,同樣需要配置s.dependency,以CJLBase為例,需要引用CJLService
//********1、修改 podspec 文件
s.dependency 'CJLServices'

//********2、修改 podfile 文件
pod 'CJLServices', :path => '../../CJLServices'
  • 如果需要加載資源,例如圖片、json、bundle文件等
    • 1、在模塊的Assets文件夾 中添加資源文件
    • 2、在specs里配置資源路徑(必須配置!!否則無法讀取資源)
    • 3、訪問時需要指定資源文件路徑
//*****1、修改 podspec 文件
s.resource_bundles = {
     'CJLBase' => ['CJLBase/Assets/*']
   }
   
//*****2、使用
let bundlePath: String = Bundle.init(for: dynamicClass.self).resourcePath! + "/CJLBase.bundle"
let bundle = Bundle(path: bundlePath)
if let path = bundle?.path(forResource: "mouse", ofType: "jpg"){
    self.imgView.image = UIImage(contentsOfFile: path)
}           

同理,模塊中的xib,json文件的獲取方式也是一樣的

4、提交至git

這里提交至git的模塊是pods工程才可以,以CJLBase為例

  • 需要在github上創建一個私有repository,命名為CJLBase

  • 執行以下終端命令

$git init
$git add .
$ git commit -am "第一次提交" 
//即第一個步驟中創建的倉庫地址
$ git remote add origin https://github.com/xxx/CJLBase.git
 
$ git push origin master 
//一定要有標簽,不然會有下面的警告
//podspec文件中獲取Git版本控制的項目需要tag號,
$ git tag -m "first release" "0.1.0" 
$ git push --tags 

5、驗證podspec文件

執行終端命令 pod spec lint

注意:pod spec相對于pod lib會更為精確,

  • pod lib相當于只驗證一個本地倉庫,
  • pod spec會同時驗證本地倉庫和遠程倉庫。

6、提交到私有倉庫

執行以下命令

pod repo push [本地Spec Repo名稱][podspec文件路徑]
 
//******舉例
$ pod repo push MySpecs CJLBase.podspec

提交成功后,可在本地倉庫中看到提交路徑MySpecs -> CJLBase

7、使用

  • 新建一個工程,在項目的podfile里添加
#私有spec倉庫的地址,而不是某個pod倉庫的地址
source 'https://github.com/xxx/MySpecs'
pod 'CJLBase'
  • 執行pod install即可

參考鏈接

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,208評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,746評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,666評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,477評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,960評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,200評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,726評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,617評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,807評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,049評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,425評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,674評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,432評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,769評論 2 372