人生"碼農(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é)如下:

一、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方案原理:
- 每個(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+JumpTools和Target_ClassController類,具體代碼見下圖:

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

注意:
在
CTMediator+JumpTools類中[self performTarget:<#(NSString *)#> action:<#(NSString *)#> params:<#(NSDictionary *)#> shouldCacheTarget:<#(BOOL)#>];這個(gè)方法Target和action的字符串不是隨便填寫的,是按照一定的規(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)建類名以及方法名即可。