iOS 組件間方案 -- MGJRouter& CTMediator

人生"碼農(nóng)"無閑暇,忙里偷閑得幾回。最近在思考項(xiàng)目項(xiàng)目組件化的問題,重翻了前段時(shí)間iOS圈關(guān)于組件化的討論,這里做下梳理和自己的總結(jié)。

說到組件化的技術(shù)方案,最早是Limboy分享了一篇蘑菇街組件化的技術(shù)方案,接著Casa提出了不同意見,后來Limboy在Casa反饋之上對自己方案做了進(jìn)一步優(yōu)化,最后Bang在前三篇文章基礎(chǔ)之上做了清晰的梳理總結(jié)。通讀之后,獲益頗多,現(xiàn)總結(jié)如下:

組件001.png

一、MGJRouter的簡單使用

蘑菇街團(tuán)隊(duì)提供了MGJRouter路由庫,使用比較簡單,其原理主要是通過注冊URL來實(shí)現(xiàn)路由跳轉(zhuǎn)。主要有兩個(gè)步驟:
① 注冊URL生成路由表
② openUrl實(shí)現(xiàn)跳轉(zhuǎn)

應(yīng)用場景:

1.vc之間的跳轉(zhuǎn)(傳值/反向傳值)
核心代碼如下:
(1).注冊URL
NS_ASSUME_NONNULL_BEGIN

@interface RouterManager : NSObject

@end

NS_ASSUME_NONNULL_END

#import "RouterManager.h"
#import <MGJRouter.h>
#import "TestOneViewController.h"
#import "TestTwoViewController.h"

@implementation RouterManager

+(void)load {
 
    [MGJRouter registerURLPattern:@"mgj://loadFirstViewController" toHandler:^(NSDictionary *routerParameters) {
        BaseNavigationController *navigationVC = routerParameters[MGJRouterParameterUserInfo][@"navigationVC"];
        FirstViewController *vc = [[FirstViewController alloc] init];
        [navigationVC pushViewController:vc animated:YES];
    }];
    
    
    [MGJRouter registerURLPattern:@"mgj://loadSecondViewController" toHandler:^(NSDictionary *routerParameters) {
        UINavigationController *navigationVC = routerParameters[MGJRouterParameterUserInfo][@"navigationVC"];
        NSString *labelText = routerParameters[MGJRouterParameterUserInfo][@"text"];
        SecondViewController *vc = [[SecondViewController alloc] init];
        vc.labelText = labelText;
        [navigationVC pushViewController:vc animated:YES];
    }];
    
    
    [MGJRouter registerURLPattern:@"mgj://loadThirdViewController" toHandler:^(NSDictionary *routerParameters) {
        UINavigationController *navigationVC = routerParameters[MGJRouterParameterUserInfo][@"navigationVC"];
        void(^block)(NSString *) = routerParameters[MGJRouterParameterUserInfo][@"block"];
        ThirdViewController *vc = [[ThirdViewController alloc] init];
        vc.clicked = block;
        [navigationVC pushViewController:vc animated:YES];
    }];
    
    [MGJRouter registerURLPattern:@"mgj://loadFourthViewController" toObjectHandler:^id(NSDictionary *routerParameters) {
        NSString *labelText = routerParameters[MGJRouterParameterUserInfo][@"text"];
        FourthViewController *vc = [[FourthViewController alloc] init];
        vc.labelText = labelText;
        return vc;
    }];
    
}
@end

(2).調(diào)用url
- (IBAction)firstClick:(UIButton *)sender {
    [MGJRouter openURL:@"mgj://loadFirstViewController"
          withUserInfo:@{@"navigationVC" : self.navigationController}
            completion:nil];
}

- (IBAction)secondClick:(UIButton *)sender {
    [MGJRouter openURL:@"mgj://loadSecondViewController"
          withUserInfo:@{@"navigationVC" : self.navigationController,
                         @"text": @"我喜歡出發(fā)"
                        }
            completion:nil];
}


- (IBAction)thirdClick:(UIButton *)sender {
    [MGJRouter openURL:@"mgj://loadThirdViewController"
          withUserInfo:@{@"navigationVC" : self.navigationController,
                         @"block":^(NSString * text){
        NSLog(@"%@",text);
    },
                       }
            completion:nil];
}

- (IBAction)fourClick:(UIButton *)sender {
    NSString *textStr = @"模擬器32位處理器測試需要i386架構(gòu),模擬器64位處理器測試需要x86_64架構(gòu),真機(jī)32位處理器需要armv7,或者armv7s架構(gòu),真機(jī)64位處理器需要arm64架構(gòu)";
      [self.navigationController pushViewController:[MGJRouter objectForURL:@"mgj://loadFourthViewController" withUserInfo:@{@"text" : textStr}] animated:YES];
}

可打印看下routerParameters字典的內(nèi)容:

{
    MGJRouterParameterCompletion = "<__NSGlobalBlock__: 0x10cae0208>";
    MGJRouterParameterURL = "mgj://loadTestOneViewController";
    MGJRouterParameterUserInfo =     {
        navigationVC = "<BaseNavigationController: 0x7f9e6501f400>";
    };
}

MGJRouter的簡單使用就是這樣,但是看這里不知道大家是否和我一樣,有個(gè)疑惑,程序運(yùn)行load方法會(huì)自動(dòng)執(zhí)行,為什么要在load方法里面寫呢,接著往下看。。。

2. MGJRouter的弊端

① 每個(gè)業(yè)務(wù)組件,都需要一來這個(gè)MGJRouter框架
② URL維護(hù)成本高(url字符串寫錯(cuò),則不執(zhí)行操作)
基于MGJRouter有以上弊端,這里引入Target-action方案,采用的是 CTMediator 這套方案.

target-action.png
target-action方案原理:
  • 每個(gè)組件, 提供一個(gè)統(tǒng)一披露的接口文件
  • 額外的維護(hù)一個(gè)中間件的分類擴(kuò)展(在此處進(jìn)行硬解碼 通過運(yùn)行時(shí)進(jìn)行物理解耦)
  • 其他地方通過target-action;的方案進(jìn)行交互

這里如何把模塊做成私有pods就不過多介紹了,我這里就簡單介紹下 CTMediator 庫 但是用方法,沒有按照標(biāo)準(zhǔn)的私有庫結(jié)構(gòu)去創(chuàng)建工程,具體可參考Target-Action方案主工程 Demo中的工程結(jié)構(gòu),這個(gè)是標(biāo)準(zhǔn)的組件庫目錄.
步驟:
(1).在項(xiàng)目中導(dǎo)入/pod 下CTMediator
(2).創(chuàng)建CTMediator+JumpToolsTarget_ClassController類,具體代碼見下圖:

code.png

我們再看下Target_ClassController類里面的代碼,如圖:

code2.png

注意:

CTMediator+JumpTools類中[self performTarget:<#(NSString *)#> action:<#(NSString *)#> params:<#(NSDictionary *)#> shouldCacheTarget:<#(BOOL)#>]; 這個(gè)方法Targetaction的字符串不是隨便填寫的,是按照一定的規(guī)則來的,而且Target_ClassController類名字一定要以Target_XXXX來開頭,而且Target_XXXX里面的方法,也一定要以-(void)Action_為開頭,具體原因是因?yàn)?code>Casa大佬的這個(gè)CTMediator庫,里面的performTarget方法就是以Target_Action_開頭的,具體實(shí)現(xiàn)原理可以看CTMediator庫源碼中的實(shí)現(xiàn), 當(dāng)然你也可以修改Casa大佬的庫的源碼,也就一個(gè)類,但是如果你是pod到項(xiàng)目中的方式,不建議修改,就按照這種規(guī)則創(chuàng)建類名以及方法名即可。

Demo下載地址.

再強(qiáng)調(diào)下,這里我這個(gè)CTMediator的Demo,不是按照標(biāo)準(zhǔn)的組件庫的形式來舉例子的,只是介紹下CTMediator庫的用法,具體可參考Target-Action方案主工程 Demo中的工程結(jié)構(gòu),這個(gè)是標(biāo)準(zhǔn)的組件庫目錄.
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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