前言
上周嘗試著對新項(xiàng)目進(jìn)行了組件化的嘗試,開始選擇的是蘑菇街的方案(文章1枯芬、文章2)论笔,但是后來發(fā)現(xiàn)所有的組件都需要在+(void)load
方法中注冊,這個讓我十分抵觸千所,然后因?yàn)轫?xiàng)目時間原因狂魔,就暫時方式了該方案。今天在看戴銘大神
的博客是發(fā)現(xiàn)了基于CTMediator 擴(kuò)展的ArchitectureDemo淫痰,然后想起來casatwy大神
當(dāng)時也有一套解決方案 iOS應(yīng)用架構(gòu)談 組件化方案最楷,今天就來學(xué)習(xí)一下,然后寫個練習(xí)的demo待错。
重點(diǎn)
本文內(nèi)容基本都是基于casatwy的文章在現(xiàn)有工程中實(shí)施基于CTMediator的組件化方案的練習(xí)籽孙,大家可以對照的看一下。
實(shí)現(xiàn)步驟
在github上創(chuàng)建私有倉庫
添加私有倉庫索引到本地
pod repo add WJPrivatePods https://github.com/pengwj/WJPrivatePods.git
在本地新建文件夾
在本地新建文件夾WJCTMediatorProject火俄,然后下載casatwy的源碼https://github.com/ModulizationDemo/MainProject文件夾中蚯撩。目錄結(jié)構(gòu)如下:
WJCTMediatorProject
└── MainProject
MainProject下載后,在MainProject目錄下執(zhí)行一下pod install
拉取一下工程依賴的庫烛占,然后設(shè)置File->Workspace Setting->Build System
為Legacy Build System
。
配置私有庫文件工具腳本
由于casatwy提供的工具腳本沟启,github.com:casatwy/ConfigPrivatePod.git
好像已經(jīng)無法拉取了忆家,所有后面需要我們手動配置私有庫迹炼。這里就先不配置了叛本。
創(chuàng)建私有Pod工程和Category工程
跟著casatwy的博客來,此次組件化的實(shí)施目標(biāo)就是把A業(yè)務(wù)組件化出來抑淫,首頁和B業(yè)務(wù)都還放在主工程胳搞。
為了把A業(yè)務(wù)抽出來作為組件卸例,我們需要為此做兩個私有Pod:A業(yè)務(wù)Pod(以后簡稱A Pod)、方便其他人調(diào)用A業(yè)務(wù)的CTMediator category的Pod(以后簡稱A_Category Pod)肌毅。
先創(chuàng)建A Pod
由于沒有私有庫配置腳本筷转,我們需要通過pod lib create NAME
來新建A Pod,通過cd指令到Project目錄下悬而,然后執(zhí)行pod lib create NAME
指令呜舒。
pod lib create A
A為我們的NAME。執(zhí)行后需要填寫一些信息笨奠,如下圖袭蝗。
此時你的主工程應(yīng)該就沒有A業(yè)務(wù)的代碼了,然后你的A工程應(yīng)該是這樣:
創(chuàng)建A_Categoty pod
重復(fù)上一步操作般婆,通過cd指令到Project目錄下到腥,然后執(zhí)行pod lib create NAME
指令創(chuàng)建名為A_Categoty的pod。
配置A_Categoty
然后去A_Category下蔚袍,在Podfile中添加一行pod "CTMediator"乡范,在A_Category.podspec文件的后面添加s.dependency "CTMediator",然后執(zhí)行pod install --verbose。
接下來打開A_Category.xcworkspace篓足,把Example同目錄下的名為A_Category的目錄拖放到Xcode對應(yīng)的位置下段誊。
然后在這里新建基于CTMediator的Category:CTMediator+A。最后你的A_Category工程應(yīng)該是這樣的:
配置主工程
去主工程的Podfile下添加pod "A_Category", :path => "../A_Category"來本地引用A_Category栈拖。
把主工程中的AViewController頭文件引用改成#import <A_Category/CTMediator+A.h>
然后執(zhí)行pod install
拉取一下A_Category鏈接连舍。這個時候主工程依然無法編譯通過。
打開主工程涩哟,在Development Pods
目錄下面找到CTMediator+A.h
索赏,在里面添加一個方法:
- (UIViewController *)A_aViewController;
再去CTMediator+A.m中,補(bǔ)上這個方法的實(shí)現(xiàn):
- (UIViewController *)A_aViewController
{
/*
AViewController *viewController = [[AViewController alloc] init];
*/
return [self performTarget:@"A" action:@"viewController" params:nil shouldCacheTarget:NO];
}
最后把主工程調(diào)用AViewController
的地方改為基于CTMediator Category的實(shí)現(xiàn):
UIViewController *viewController = [[CTMediator sharedInstance] A_aViewController];
[self.navigationController pushViewController:viewController animated:YES];
編譯一下贴彼,如果能運(yùn)行成功潜腻,并出現(xiàn)下面界面,就表示已經(jīng)完成了對主工程的改造器仗。
添加Target-Action融涣,并讓A工程編譯通過
打開A_Category工程和A工程,在A工程中創(chuàng)建一個文件夾:Targets精钮,然后看到A_Category里面有performTarget:@"A"威鹿,所以我們新建一個對象,叫做Target_A轨香。
然后又看到對應(yīng)的Action是viewController忽你,于是在Target_A中新建一個方法:Action_viewController。這個Target對象是這樣的:
頭文件:
#import <UIKit/UIKit.h>
@interface Target_A : NSObject
- (UIViewController *)Action_viewController:(NSDictionary *)params;
@end
實(shí)現(xiàn)文件:
#import "Target_A.h"
#import "AViewController.h"
@implementation Target_A
- (UIViewController *)Action_viewController:(NSDictionary *)params
{
AViewController *viewController = [[AViewController alloc] init];
return viewController;
}
@end
添加B_Category
同上面創(chuàng)建A_Categoty pod
和配置A_Categoty
的步驟臂容,CTMediator+B的實(shí)現(xiàn)如下:
//頭文件:
#import <CTMediator/CTMediator.h>
#import <UIKit/UIKit.h>
@interface CTMediator (B)
- (UIViewController *)B_viewControllerWithContentText:(NSString *)contentText;
@end
//實(shí)現(xiàn)文件:
#import "CTMediator+B.h"
@implementation CTMediator (B)
- (UIViewController *)B_viewControllerWithContentText:(NSString *)contentText
{
/*
BViewController *viewController = [[BViewController alloc] initWithContentText:@"hello, world!"];
*/
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
params[@"contentText"] = contentText;
return [self performTarget:@"B" action:@"viewController" params:params shouldCacheTarget:NO];
}
@end
文件目錄如下:
然后我們對應(yīng)地在A工程中修改頭文件引用為#import <B_Category/CTMediator+B.h>科雳,并且把調(diào)用的代碼改為:
UIViewController *viewController = [[CTMediator sharedInstance] B_viewControllerWithContentText:@"hello, world!"];
[self.navigationController pushViewController:viewController animated:YES];
再編譯一下,發(fā)現(xiàn)編譯依然失敗了脓杉,這是因?yàn)锳工程中沒有導(dǎo)入相關(guān)pod糟秘。打開A工程的Podfile文件,添加如下的配置項(xiàng)球散。然后執(zhí)行pod install
// 后面的“path”需要注意一下蚌堵,這個需要根據(jù)你的項(xiàng)目情況配置
pod "B_Category", :path => "../../B_Category"
// 這個是casatwy源碼中依賴的布局庫
pod 'HandyFrame'
新增Target_B對象
打開主工程MainProject
,然后新建Target_B對象
//Target_B頭文件:
#import <UIKit/UIKit.h>
@interface Target_B : NSObject
- (UIViewController *)Action_viewController:(NSDictionary *)params;
@end
//Target_B實(shí)現(xiàn)文件:
#import "Target_B.h"
#import "BViewController.h"
@implementation Target_B
- (UIViewController *)Action_viewController:(NSDictionary *)params
{
NSString *contentText = params[@"contentText"];
BViewController *viewController = [[BViewController alloc] initWithContentText:contentText];
return viewController;
}
@end
然后編譯運(yùn)行一下MainProject,看看能不能成功跳轉(zhuǎn)沛婴,如果不能成功跳轉(zhuǎn)可以按照下面順序檢查一下Podfile
文件吼畏。
// MainProject的Podfile文件
pod 'HandyFrame'
pod "A_Category", :path => "../A_Category"
pod "B_Category", :path => "../B_Category"
pod "A",:path => "../A"
pod 'CTMediator'
// A工程的Podfile文件
pod "B_Category", :path => "../../B_Category"
pod 'HandyFrame'
// A_Category工程的Podfile文件
pod 'A_Category', :path => '../'
pod "CTMediator"
// B_Category工程的Podfile文件
pod 'B_Category', :path => '../'
pod "CTMediator"
這里先上傳一份未發(fā)版的工程文件,大家可以對照一下嘁灯。
https://github.com/pengwj/blogWork/blob/master/code/WJCTMediatorProject.zip
私有Pod發(fā)版
我們創(chuàng)建了三個私有Pod:A泻蚊、A_Category、B_Category丑婿,接下來我們要給這三個私有Pod發(fā)版性雄,發(fā)版之前去podspec里面確認(rèn)一下版本號和dependency没卸。
私有庫發(fā)版折騰失敗了,還在研究中秒旋。约计。。
推薦閱讀
iOS應(yīng)用架構(gòu)談 組件化方案
在現(xiàn)有工程中實(shí)施基于CTMediator的組件化方案
iOS關(guān)于CTMediator組件化實(shí)踐的詳解篇
iOS組件化開發(fā)之路(CTMediator)迁筛,涉及到cocoapods本地庫煤蚌、遠(yuǎn)程私有庫、遠(yuǎn)程公開庫