iOS CTMediator組件化實(shí)踐

3篇文章帶你學(xué)會(huì)組件化??????
1.iOS 創(chuàng)建遠(yuǎn)程cocoapods 私有庫(kù)
2.iOS Pod 私有庫(kù)創(chuàng)建(自定義的組件)
3.iOS CTMediator組件化實(shí)踐

首先你要懂得組件化的整體思想,如下圖,就是通過(guò)一個(gè)中間者傳遞信息,用來(lái)降低模塊間的耦合度, 從而達(dá)到高內(nèi)聚低耦合的目的.

組件化思想

提到的中間層就是CTMediator, GitHub上面介紹的非常詳細(xì), 還有使用文章推薦.

廢話不多說(shuō), 開始實(shí)踐:

  • 目的: 項(xiàng)目的ViewController 的touchesBegan方法push 新界面(AViewController); 分解成通過(guò)CTMediator 和組件通信獲取aVc , 來(lái)達(dá)到相同功能.
    普通->組件

步驟詳解

1. 創(chuàng)建組件A_Section, 可參考前一篇文章自定義組件

  1. GitHub 上創(chuàng)建A_Section組件遠(yuǎn)程倉(cāng)庫(kù)
  2. 創(chuàng)建本地項(xiàng)目 (pod lib create A_Section)
  3. 修改.podspec 文件中的homepage 和source 和version
#發(fā)版版本號(hào),每更新一次代碼就改變一次版本號(hào)
s.version      = "0.0.1"
#你的 git 倉(cāng)庫(kù)首頁(yè)的網(wǎng)頁(yè) url,注意并不是 https/ssh這種代碼倉(cāng)庫(kù)地址
s.homepage     = "https://xxxxxxxxx/A_Section"
#這里就是你 git 倉(cāng)庫(kù)的 https/ssh 地址了
s.source       = { :git => "git@gitxxxxxxxx/A_Section.git", :tag => "#{s.version}" }
  1. 創(chuàng)建AViewController 和 Target_A 文件, 在選擇文件夾的時(shí)候記得選classes
    組件內(nèi)添加內(nèi)容

    : 一個(gè)組件對(duì)應(yīng)一個(gè) Target_A, 這里要特殊記憶下Target_AAAction_viewControllerviewController ;
// Target_A.h文件
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface Target_A : NSObject

/// 獲取該組件的AViewController 的實(shí)例化對(duì)象
- (UIViewController *)Action_viewController:(NSDictionary *)params;

@end

// Target_A.m 文件
#import "Target_A.h"
#import "AViewController.h"

@implementation Target_A

- (UIViewController *)Action_viewController:(NSDictionary *)params
{
    AViewController *viewController = [[AViewController alloc] init];
    return viewController;
}

@end
  1. 這時(shí)的A_Section工程目錄應(yīng)該是這樣的:
    當(dāng)前工程目錄
  2. 提交組件項(xiàng)目更新內(nèi)容, 組件發(fā)版打tag, 將repo源添加到自己的私有repo索引庫(kù)中.可參考自定義組件5~8步驟

2. 創(chuàng)建中間件A_Category(CTMediator 的Category)

  1. 同一業(yè)務(wù)模塊使用同一中間件就可以, 這里只是文件夾名稱, 可隨意, 這里使用A_Category
  2. 創(chuàng)建遠(yuǎn)程倉(cāng)庫(kù)A_Category
  3. 修改.podspec 文件, 依賴CTMediator 第三方庫(kù)
  4. cd /A_Section/Example 目錄下, 更新(pod update --no-repo-update)
  5. 創(chuàng)建CTMediator 的分類CTMediator+A
  6. CTMediator (A)內(nèi)部實(shí)現(xiàn)如下:
// CTMediator+A.h 內(nèi)容
#import <CTMediator/CTMediator.h>
@interface CTMediator (A)
- (UIViewController *)getAViewController;
@end

// CTMediator+A.m 內(nèi)容
#import "CTMediator+A.h"
@implementation CTMediator (A)
- (UIViewController *)getAViewController
{
    /*
        AViewController *viewController = [[AViewController alloc] init];
     */
    // 這個(gè)方法就牛逼了, CTMediator 會(huì)自動(dòng)去找Target_A 的類, 并且去尋找是否存在viewController 方法, 存在就去實(shí)現(xiàn)
    return [self performTarget:@"A" action:@"viewController" params:nil shouldCacheTarget:NO];
}
@end

: 還記得步驟一第四小步需要特殊記憶的Target_AAAction_viewControllerviewController嗎? 其實(shí)對(duì)應(yīng)的就是performTarget:@"A"中的Aaction:@"viewController"中的viewController , 名字都可以隨便起, 但是必須是在對(duì)應(yīng)的前提下;

  1. 配置之后的文件結(jié)構(gòu):
    A_Category結(jié)構(gòu)目錄
  2. 提交組件項(xiàng)目更新內(nèi)容, 組件發(fā)版打tag, 將repo源添加到自己的私有repo索引庫(kù)中.可參考自定義組件5~8步驟

3. 本地創(chuàng)建主工程MainProject

  1. 就是創(chuàng)建個(gè)名字為MainProject(名稱可隨意) 的Xcode項(xiàng)目, pod init -> pod install 操作完成即可.
  2. 盡量保證A_Section 和A_Category 和MainProject 在同一文件夾下或同級(jí)目錄下, 方便后續(xù)操作.
    我的文件位置, 都在桌面上了

4. 本地組件測(cè)試

  1. cd至MainProject目錄下, 修改profile 文件:
target 'ManiProject' do
  use_frameworks!

    #組件化依賴
    pod 'CTMediator'
  
    #本地測(cè)試
    pod 'A_Category', :path => '../A_Category'
    pod 'A_Section',  :path => '../A_Section'

end

: pod 'A_Category', :path => '../A_Category'代表在當(dāng)前的podfile目錄下, (../)返回上一級(jí)目錄, 找到A_Category文件, 拉取其中A_Category.podspec文件.

  1. 更新庫(kù)文件( pod install)
  2. 測(cè)試組件是否能正常使用, MainProject中的ViewController 類中測(cè)試push 功能
// ViewController.m文件內(nèi)容
#import "ViewController.h"

// 引入中間件頭文件
#import <A_Category/CTMediator+A.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // aVc 其實(shí)就是AViewController
    UIViewController *aVc = [[CTMediator sharedInstance] getAViewController];
    [self.navigationController pushViewController:aVc animated:YES];
}
@end

: 引入A_Category的頭文件, 通過(guò)[[CTMediator sharedInstance] getAViewController]獲取組件提供的東西.

這個(gè)時(shí)候能正常實(shí)現(xiàn)push 功能, 就算本地的組價(jià)可以正常使用了.

4. 遠(yuǎn)程倉(cāng)庫(kù)的組件的使用測(cè)試

  1. 修改podfile 文件, 添加私有源repo索引庫(kù).不會(huì)的話可參考創(chuàng)建遠(yuǎn)程cocoapods 私有庫(kù)
  2. 添加需要使用組件的依賴
    podfile 文件大致為:
#這是GitHub的源索引庫(kù)
source 'https://github.com/CocoaPods/Specs.git'
#這是我自己的組件的源索引庫(kù)
source 'git@github.com:LiHe0308/PrivateSpecs.git'

target 'ManiProject' do
  use_frameworks!

    #組件化依賴
    pod 'CTMediator'
  
    #組件
    pod 'A_Category'
    pod 'A_Section'

end
  1. 主工程pod install 更新庫(kù)文件
  2. 測(cè)試push 功能, 代碼一點(diǎn)不需要變

這時(shí)候功能正常, 就代表遠(yuǎn)程組件可以正常使用了.

總結(jié)注意點(diǎn):

  • 主工程、組件、之間的關(guān)系

 1. 組件A_Section: 將相當(dāng)于正常開發(fā)的一個(gè)文件夾, 但是多了一個(gè)Target_A類, Target_A中對(duì)外(CTMediator 的分類)開放整個(gè)組件的功能,所以整個(gè)組件的功能都寫在Target_xName中.例:
 - (UIViewController *)Action_viewController:(NSDictionary *)params;
 
 2. A_Category: 主要是使用CTMediator 的分類,CTMediator (A), 重點(diǎn)就是命名, 一定要和組建中Target后面的名稱相同, 也就是A.
    通過(guò)方法return [self performTarget:@"A" action:@"viewController" params:nil shouldCacheTarget:NO];實(shí)現(xiàn)和組件通信, 獲取自動(dòng)尋找Target_A 文件中的viewController 來(lái)執(zhí)行
    然后封裝方法 - (UIViewController *)getAViewController; 供外界使用.
 
 3. 主工程ManiProject: 就是你所做的項(xiàng)目, 它只與CTMediator (A)通訊, 引入頭文件,
    通過(guò)分類中自定義的方法[[CTMediator sharedInstance] getAViewController]; 獲取到組件
  • 代碼的提交順序, 嚴(yán)格遵守!!!

 1. 一定要先提交所有變更信息
 git remote add origin git@github.com:xxx.git
 git add .
 git commit -a -m "提交變更信息"
 git push -u origin HEAD
 
 2. 修改xxxxx.podspec 文件中homepage 和 source, 一定要準(zhǔn)確
    s.homepage   ->  你的 git 倉(cāng)庫(kù)首頁(yè)的網(wǎng)頁(yè) url,注意并不是 https/ssh這種代碼倉(cāng)庫(kù)地址
    s.source     ->  這里就是你 git 倉(cāng)庫(kù)的 https/ssh 地址了
 
 3. 修改s.version
    s.version = 0.2.0
 
 4. 發(fā)版 -> 一定要與.podspec 文件中s.version 相同
 git tag 0.2.0
 git push origin 0.2.0
 
 5. 將組建repo 地址推到私有源索引庫(kù)中 (只做一次就可以, 且必須在.podspec同級(jí)目錄下操作)
 pod repo push [私有源名稱] 組件名稱.podspec --allow-warnings
  • 關(guān)于 xib 和圖片

組件中若用到了圖片,或者 xib 資源,要指定資源的文件路徑,否則不會(huì)把圖片打包到你的組件中:

s.resource_bundles = {
    'A_Section' => ['A_Section/AImages/**/*.{png}', 'A_Section/Classes/*.{xib}']  
}
或者
s.resources = ['A_Section/AImages/**/*.{png}', 'A_Section/Classes/*.{xib}']

如果使用 Xocde 工程自帶的 Assets 那個(gè)文件夾的話,圖片也無(wú)法打包到組件中,最好自己重新創(chuàng)建一個(gè)新的文件夾用來(lái)存放圖片資源;
然后代碼中獲取 xib, png 等 resource 時(shí),bundle 重新設(shè)置,這樣就保證了無(wú)論在組件中,還是在 MainProject 工程中,都可以配置到正確的 Bundle,如果你使用 s.resource_bundles={},配置了自定義的 bundle名稱,那么 [bundle pathForResource:@"A_Section" ofType:@"bundle"]中就要替換成相應(yīng)的名稱.

//mainBundle
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *bundlePath = [bundle pathForResource:@"A_Section" ofType:@"bundle"];
    if (bundlePath)
    {
       //組件資源所在的 bundle     
       bundle = [NSBundle bundleWithPath:bundlePath];
    }

.End

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

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

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