教你如何從0到1實現(xiàn)組件化架構(gòu)

前言

本篇主要講解組件化架構(gòu)思想,從零教你如何組件化一個項目。

如果喜歡我的文章,可以關(guān)注我微博:袁崢Seemygo

為什么要組件化

  • 隨著項目的不斷迭代,各個模塊會越來越復(fù)雜,各個模塊相互依賴,而且每個模塊可能會有共同的業(yè)務(wù)邏輯,導(dǎo)致整個項目維護(hù)起來比較麻煩。
  • 可以采用組件化,把每個業(yè)務(wù)邏輯和模塊分離,單獨管理,這樣比較方便維護(hù),各個開發(fā)人員只需要關(guān)心好自己的模塊就好了。

組件化好處

  • 分工更加明確,提高開發(fā)效率
  • 復(fù)用性更好,能迅速的組成更多的App

組件化思想

  • 就好比封裝控件,復(fù)雜的控件一般都會封裝,組件化只不過是把每個模塊單獨抽出來,作為一個小工程,然后在組成一個一個完整的項目。

如何組件化

  • 使用cocoapods管理組件化開發(fā)
    • podspec:描述自己組件工程的代碼目錄和資源目錄在哪,還有自己組件工程所依賴其他框架,到時候就會根據(jù)podspec的指引去引入自己的倉庫代碼.

      • 命令:pod spec create spec文件名
          // 創(chuàng)建pod索引庫,固定寫法,并且定義索引庫的名字為s,后續(xù)通過s,就能拿到索引庫
          Pod::Spec.new do |s|
          
            // 設(shè)置名稱
            s.name         = "HttpManager"
          
            // 設(shè)置版本號
            s.version      = "0.0.1"
          
            // 設(shè)置摘要
            s.summary      = "A short description of HttpManager."
          
            // 設(shè)置詳情
            s.description  = "Good"
          
            // 設(shè)置倉庫主頁
            s.homepage     = "http://EXAMPLE/HttpManager"
          
            // 設(shè)置許可證
            s.license      = "MIT"
          
            // 設(shè)置作者
            s.author             = { "iThinkerYZ" => "690423479@qq.com" }
          
            // 設(shè)置倉庫源,表示在哪可以找到組件工程
            s.source       = { :git => "", :tag => "#{s.version}" }
          
            // 設(shè)置 源文件路徑 => 不是整個工程的文件,而是自己封裝的代碼,以后別的工程引入,就會引入這里的代碼。
            s.source_files  = "HttpManager/Classes/**/*.{h,m}"
          
           // s.dependency = '' 組件工程依賴哪些第三方框架
           // s.frameworks = 'UIKit', 'MapKit' 組件工程依賴哪些原生框架
           // s.resource_bundles = {} 組件工程圖片資源
           
          end
      
      
      • podspec文件注意點:s.source_files僅僅描述組件代碼就好,不要描述整個工程名文件,會把所有文件集成上去,錯誤寫法:s.source_files = "HttpManager"

      • **:表示所有文件:因為*表示通配符,可有可無.

        • s.source_files = "HttpManager/Classes/**/*.{h,m}",表示組件代碼在podspec目錄下HttpManager/Classes中的所有文件,默認(rèn)會自動追蹤到到podspec文件的目錄路徑下,因為當(dāng)前處于podspec文件中,處于哪個文件,就自動追蹤哪個文件。
        • HttpManager/Classes/a.h 匹配到的應(yīng)該是HttpManager/Classes/**,表示HttpManager/Classes/a.h后沒有東西,就不會在找,直接匹配到。
      • podspec文件注意點:s.description:不能為空

      • podspec文件注意點:s.license:不能亂填,必須是有這樣的協(xié)議,比如(MIT)

    • podFile文件:指定主工程加載哪些組件庫,里面描述好組件庫對應(yīng)的podspec文件在哪,就知道去哪加載組件代碼。

      • 創(chuàng)建命令:pod init
      • cocoapods可以加載遠(yuǎn)程倉庫也可以加載本地倉庫,一般加載遠(yuǎn)程倉庫.
      • 如何加載本地倉庫代碼?
        1. 本地倉庫代碼搞一個podspec文件描述去哪加載組件代碼

        2. 誰需要引入本地倉庫代碼,就創(chuàng)建Podfile

        3. Podfile:指定podspec文件在哪

          pod 'HttpManager' , :path => '../HttpManager'
          
          • ../HttpManager:回到Podfile上一級目錄,進(jìn)入HttpManager就能找到podspec
          • Podfile在哪,就自動跟隨在哪級目錄
Podfile文件.png
podspec文件.png
  • 創(chuàng)建組件工程
    • 方式一: 直接創(chuàng)建工程,把組件代碼放在Class中,只要spec描述好,就會自動加載Class中組件代碼
      • 生成spec描述文件,指定加載組件工程的組件代碼在哪。
    • 方式二: 使用cocoapods命令:pod lib create 組件代碼名稱
      • 這個命令會自動生成一套組件代碼工程測試代碼,并且有Git管理


        Snip20170223_16.png
      • 還會生成podspec,描述好組件代碼在哪就好.
      • 如何使用自動生成的組件工程代碼?
        1. 需要把自己的組件代碼放在Class中對應(yīng)文件,還不夠,發(fā)現(xiàn)根本沒法引入組件代碼.h文件.

        2. 需要重新pod install,因為不重新pod install,Example工程根本不知道Pod更新了,pod install的作用:重新讓pod庫與所依賴的工程文件產(chǎn)生關(guān)聯(lián)。

Cocopods原理

  1. 根據(jù)Podfile描述,找到對應(yīng)代碼庫的描述文件podspec
  2. podspec中描述,去哪(s.source)才能找到代碼庫,并且找到之后,需要拷貝哪些文件(s.source_files)到自己的工程中。

如何組件化(公共遠(yuǎn)程倉庫)

  • 問題:以上的代碼倉庫都在本地,沒有遠(yuǎn)程管理,也就意味著只能自己使用,別人不能使用,如果想把自己的代碼倉庫開源,讓所有的開發(fā)人員都可以弄,應(yīng)該怎么做?
  • 把自己的倉庫代碼推送到cocoapods中索引庫中就好了。
    • 原理:我們之前安裝cocoapods時,有一步驟pod setup,這一步其實就是去下載cocoapods中公共的所有代碼倉庫索引,保存到本地
    • 通過pod repo 指令就能查看cocoapods的索引庫
pod path.png
  • 如何把自己代碼倉庫上傳到cocoapods上
    1. 給自己代碼倉庫,創(chuàng)建podspec,其實本質(zhì)是把自己代碼倉庫的podspec索引文件上傳上去就好了,可以直接使用pod lib create命令

    2. 自己倉庫代碼遠(yuǎn)程托管,并且公開,這樣別人才能獲取到你的倉庫代碼

      • 注意:遠(yuǎn)程倉庫不需要創(chuàng)建gitignore文件,因為pod lib創(chuàng)建了
      • 提交自己倉庫代碼到遠(yuǎn)程倉庫
      • git status : 查看狀態(tài),如果有不想要的文件,可以用gitignore忽略掉
      • 提交到本地緩存區(qū) `git add .``
      • 提交到本地倉庫 git commit -m ''
      • 查看遠(yuǎn)程倉庫地址 git remote(查看有沒有遠(yuǎn)程地址)
      • 綁定遠(yuǎn)程地址 git remote add origin 遠(yuǎn)程倉庫地址
      • 推送自己代碼到遠(yuǎn)程倉庫 git push origin master
    3. 給自己倉庫綁定Tag,因為cocoapods是根據(jù)代碼倉庫的Tag,去下載對應(yīng)Tag的遠(yuǎn)程代碼庫的。

      • 給自己當(dāng)前倉庫版本添加Tag標(biāo)簽,git tag -a 0.0.1 -m '0.0.1',僅僅是本地
      • 把本地標(biāo)簽推送到遠(yuǎn)程服務(wù)器,git push --tags
    4. 注冊trunk

      • 注冊trunk,不是任何人都能推送,因為cocoapods依賴trunk服務(wù)器管理,所以需要通過trunk推送自己的podspec(cocoapods官網(wǎng)
      • 命令:pod trunk register EMAIL [NAME]
      • pod trunk register 58999050@qq.com yuanzheng
      • 驗證成功后,點擊郵箱就好了,打開會有點慢.
    5. 推送自己的podspec到cocoapods的索引庫

      • pod trunk push HttpManager.podspec --allow-warnings
      • 注意:必須cd 進(jìn)入到podspec目錄下,才能執(zhí)行這個代碼
      • 注意:podspec文件中的s.version版本號要跟最新Tag一致
      • 注意:podspec文件中的s.source倉庫地址也不能寫錯
    6. 測試能否索引到

      • pod search 自己倉庫
      • 發(fā)現(xiàn)索引不到,其實已經(jīng)上傳到cocoapods上了,只不過需要重新更新索引文件
      • 怎么更新pod索引文件?
        • 原理:pod setup成功后會生成~/Library/Caches/CocoaPods/search_index.json文件
        • search_index.json文件文件刪除,重新執(zhí)行pod search,就會重新更新索引.

如何組件化(私有遠(yuǎn)程倉庫)

  • 問題:有些公司核心的代碼不想開源,就不能放在cocoapods公共的索引庫中,也不能放在本地,因為以后需要多人開發(fā),cocoapods支持創(chuàng)建自己的私有索引庫,只需要把自己的代碼倉庫放在自己的私有索引庫就好了.
  • 如何創(chuàng)建私有遠(yuǎn)程倉庫索引庫
    1. 搞個私有遠(yuǎn)程索引庫托管平臺

    2. 本地添加私有遠(yuǎn)程索引庫: pod repo add XMGSpec https://git.coding.net/iThinkerYZ520/XMGSpec.git,后面是索引庫遠(yuǎn)程地址

    3. 把自己私有庫的索引添加到自己私有庫種: pod repo push XMGSpec XMGLib.podspec --allow-warnings,本地索引庫就會有自己的私有庫,并且遠(yuǎn)程也會有,pod repo push會幫我們推送到遠(yuǎn)程索引庫.

  • 怎么使用自己的私有索引倉庫
    • pod search 搜索自己庫描述

    • pod install,發(fā)現(xiàn)找不到,因為默認(rèn)是去共有的索引庫查找

    • 需要在Podfile文件頂部添加一個源,表示去哪個地方查找。

      • source 'https://git.coding.net/iThinkerYZ520/XMGSpec.git'
    • 但是有問題,如果以后要添加公有的索引庫,比如AFN,就找不到了

      • 因此還需要在添加一個公有索引庫源
      • source 'https://github.com/CocoaPods/Specs.git'
      # 表示先去找私有,在找公有
      source 'https://git.coding.net/iThinkerYZ520/XMGSpec.git'
      source 'https://github.com/CocoaPods/Specs.git'
      
      target '測試私有索引庫' do
      
         pod 'XMGLib'
         pod 'AFNetworking', '~> 3.1.0'
      
      end
      

組件化升級

  • 以后各個組件要不斷更新完善,怎么管理。
    • 只需要把最新的版本代碼綁定tag,更新Podspec文件,重新上傳到版本索引庫就好了
      • pod repo push XMGSpec XMGLib.podspec --allow-warnings
    • 工程文件在使用的時候,使用pod update 就能加載最新版本組件代碼.
      • pod update --no-repo-update

組件化資源

  • 組件工程資源放哪?
    • 使用pod lib create創(chuàng)建的組件工程,有個Assets文件夾,把圖片放這
    • 然后podspec指定資源文件路徑s.resource_bundles
    • 倉庫代碼重新pod install就好了,會自動生成bundle文件,圖片就保存到這。
Snip20170213_2.png
Snip20170213_4.png
  • 因為podspec指定的圖片資源就是這個路徑,就會自動查找這個路徑.
  • 如何使用組件代碼的資源?
    • 之前獲取圖片都是在主bundle中:NSBundle mainBundle,但是組件資源代碼,不是在主bundle中,是在自己框架的bundle中
    • 獲取自己bundle,[NSBundle bundleForClass:self],self:表示當(dāng)前類,當(dāng)前方法獲取當(dāng)前類所在的bundle
      • 因為當(dāng)前方法在自己框架中,就能獲取自己的bundle


        Snip20170213_5.png
    ```
     NSBundle *selfBundle = [NSBundle bundleForClass:self];

    NSLog(@"%@",selfBundle);
    
    // 獲取bundle還不夠,圖片在bundle的XMGLib.bundle文件中
    // 注意圖片要全名
    NSString *path = [selfBundle pathForResource:@"XMGLib.bundle/圖片@2x.png" ofType:nil];
    
    UIImage *image = [UIImage imageWithContentsOfFile:path];
    
    ```
  • 注意:可能項目會遇見如圖bug
Snip20170223_19.png
  • 原因:導(dǎo)入的組件代碼有xib,但是找不到xib運行,因為xib屬于資源,不能當(dāng)成代碼導(dǎo)入,也就是需要用resource_bundles導(dǎo)入。


    Snip20170223_20.png
  • 運行:找不到xib,因為xib被存放到資源的bundle中,因此需要添加前綴
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
// 獲取當(dāng)前bundle名稱
    NSString *bundleName = bundle.infoDictionary[@"CFBundleName"];
    bundleName = [NSString stringWithFormat:@"%@.bundle",bundleName];
// xib名稱需要拼接Bundle名稱,否則找不到xib
    NSString *nibName = [NSString stringWithFormat:@"%@/XMGHomeRecommendCell",bundleName];
    [self.tableView registerNib:[UINib nibWithNibName:nibName bundle:[NSBundle bundleForClass:[self class]]] forCellReuseIdentifier:ID];
  • 友情提醒:如果組件中使用了資源,一定要把組件生成framework,不能生成.a,否則資源拿不到.
  • podfile文件中添加描述use_frameworks!
Snip20170223_21.png
  • 使用use_frameworks和不使用use_frameworks的區(qū)別
Snip20170223_22.png
Snip20170223_23.png

框架依賴

  • podspec文件中描述:s.dependency 'AFNetworking'
    • 在使用組件的時候就會自動導(dǎo)入第三方庫

如何組件化(劃分子組件)

  • 隨著組件不斷擴(kuò)大,業(yè)務(wù)也會越來越多,如果不劃分子組件,可能我們的工程有時候并不需要導(dǎo)入那么多的業(yè)務(wù),也會一起導(dǎo)入到自己工程,造成自己工程不必要的代碼太多,所以在大公司一般都會為自己的工程瘦身,就是減少不必要的代碼。
  • 一個好的組件,要劃分好子組件,別人在加載你的組件的時候,就可以根據(jù)自己的需求,加載對應(yīng)的組件代碼
  • 以SDWebImage為例,內(nèi)部有四個子組件,有一個組件專門用來加載gif圖片.
Snip20170213_7.png
  • SDWebImage的podspec文件,描述了子組件,格式固定
    • 注意:自己子組件如果依賴其他子組件,一定要寫依賴子組件,否則子組件不能用,下面就依賴Core子組件
      •  注意:GIF 和 gif不能同名,ruby語法,GIF是外界搜索子組件名稱,gif是變量,用于后面訪問
        
      •  如果使用了subspec,別人引入你的框架,代碼也會按照subspec劃分文件夾結(jié)構(gòu),否則所有代碼都在一起,不管你之前是否劃分好,比如SDWebImage就會有GIF文件夾
        
      • 還有如果使用subspec,就不需要描述整個文件夾路徑,會造成subspec劃分的文件夾沒有代碼,用#注釋掉之前的描述。
Snip20170224_28.png
s.subspec 'GIF' do |gif|
    gif.ios.deployment_target = '7.0'
    gif.source_files = 'SDWebImage/FLAnimatedImage/*.{h,m}'
    // 設(shè)置依賴,依賴自己組件的子組件Core
    gif.dependency 'SDWebImage/Core'
    gif.dependency 'FLAnimatedImage', '~> 1.0'
    gif.xcconfig = {
      'USER_HEADER_SEARCH_PATHS' => '$(inherited) $(SRCROOT)/FLAnimatedImage/FLAnimatedImage'
    }
  end

  • 使用subspec和不使用subpec區(qū)別
Snip20170223_18.png
  • 如何加載子組件

    • podfile文件描述
    // 只會引入GIF組件
    pod 'SDWebImage/GIF'
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容