在 iOS組件化方案調(diào)研 這篇中,對組件化的應用場景和實現(xiàn)方式做了簡單的調(diào)研旷余。最終在項目中采用的是 casa 的
CTMediator
這套方案。以下是CTMediator 的一個簡單的使用教程扁达。
一正卧、普通頁面跳轉用法
假設我們有個頁面叫 OneViewController
,當前頁面為 HomeViewController跪解,普通情況下頁面的間的跳轉方式如下:
#import "HomeViewController.h"
#import "OneViewController.h"
@implementation HomeViewController
- (void)aButtonClick:(UIButton *)sender {
OneViewController *viewController = [[OneViewController alloc] init];
viewController.name = @"普通用法"; //傳遞必要參數(shù)
[self.navigationController pushViewController:viewController animated:YES];
}
@end
這樣做看上去沒什么問題炉旷,實際也沒什么問題。
但是,考慮以下情況:
1窘行,如果HomeViewController
里有 N 個這樣的 button
事件饥追,每個點擊后的跳轉都是不同的頁面,那么則 HomeViewController
里抽高,需要導入 N 個這樣的 OneViewController.h
;
2判耕,如果HomeViewController
是一個可以移植到其它項目的業(yè)務模塊,在拖出首頁 HomeVC
相關的業(yè)務代碼時翘骂,難道還要把 HomeViewController.m
導入的 N 個其它 XxxViewController.h
都一塊拖到新項目中么壁熄?
這點就是因為代碼的耦合導致了首頁 HomeVC
沒法方便的移植。
說這樣沒有問題碳竟,是因為普通情況下草丧,我們并沒有移植 HomeVC
到其它項目的需求。
至于什么時候會有這樣的問題莹桅,以及昌执,這樣的問題如果解決,在 iOS組件化方案調(diào)研這篇中诈泼,已經(jīng)做過簡單的討論懂拾,這篇主要是選取了我個人較偏向的 Target-Action
這套方案,簡單講一下實現(xiàn)方式铐达。
二岖赋、Target-Action 實現(xiàn)頁面跳轉
采用的是 CTMediator
這套方案
Demo地址
還是假設我們有個頁面叫 NewsViewController
, 當前頁面為HomeViewController
那么,我們按照CTMediator
設計的架構來寫一遍這個流程
1.創(chuàng)建Target-Action
創(chuàng)建一個 Target_News
類瓮孙,在這個文件里唐断,我們主要生成 NewsViewController
實例并為其進行一些必要的賦值。例如:
// Target_News.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface Target_News : NSObject
- (UIViewController *)Action_NativeToNewsViewController:(NSDictionary *)params;
@end
這個類需要直接 #import "NewsViewController.h"
// Target_News.m
#import "Target_News.h"
#import "NewsViewController.h"
@implementation Target_News
- (UIViewController *)Action_NativeToNewsViewController:(NSDictionary *)params {
NewsViewController *newsVC = [[NewsViewController alloc] init];
if ([params valueForKey:@"newsID"]) {
newsVC.newsID = params[@"newsID"];
}
return newsVC;
}
@end
2.創(chuàng)建 CTMediator 的Category.
CTMediator+NewsActions.這個Category利用Runtime調(diào)用我們剛剛生成的Target_News杭抠。
由于利用了Runtime脸甘,導致我們完全不用#import剛剛生成的Target_News即可執(zhí)行里面的方法,所以這一步偏灿,兩個類是完全解耦的丹诀。也即是說,我們在完全解耦的情況下獲取到了我們需要的NewsViewController菩混。例如:
// CTMediator+NewsActions.h
#import "CTMediator.h"
#import <UIKit/UIKit.h>
@interface CTMediator (NewsActions)
- (UIViewController *)yt_mediator_newsViewControllerWithParams:(NSDictionary *)dict;
@end
// CTMediator+NewsActions.m
#import "CTMediator+NewsActions.h"
NSString * const kCTMediatorTarget_News = @"News";
NSString * const kCTMediatorActionNativTo_NewsViewController = @"NativeToNewsViewController";
@implementation CTMediator (NewsActions)
- (UIViewController *)yt_mediator_newsViewControllerWithParams:(NSDictionary *)dict {
UIViewController *viewController = [self performTarget:kCTMediatorTarget_News
action:kCTMediatorActionNativTo_NewsViewController
params:dict];
if ([viewController isKindOfClass:[UIViewController class]]) {
return viewController;
} else {
NSLog(@"%@ 未能實例化頁面", NSStringFromSelector(_cmd));
return [[UIViewController alloc] init];
}
}
@end
3.最終使用
由于在Target中忿墅,傳遞值得方式采用了去Model化得方式,導致我們在整個過程中也沒有#import任何Model沮峡。所以疚脐,我們的每個類都與Model解耦。
// HomeViewController.m
#import "HomeViewController.h"
#import "CTMediator+NewsActions.h"
@implementation HomeViewController
- (void)bButtonClick:(UIButton *)sender {
UIViewController *viewController = [[CTMediator sharedInstance] yt_mediator_newsViewControllerWithParams:@{@"newsID":@"123456"}];
[self.navigationController pushViewController:viewController animated:YES];
}
@end
4.不足
這里其實唯一的問題就是邢疙,Target_Action里不得不填入一些 Hard Code棍弄,就是對創(chuàng)建的VC的賦值語句望薄。不過這也是為了達到最大限度的解耦和靈活度而做的權衡。
// 1. kCTMediatorTarget_News字符串 是 Target_xxx.h 中的 xxx 部分
NSString * const kCTMediatorTarget_News = @"News";
// 2. kCTMediatorActionNativTo_NewsViewController 是 Target_xxx.h 中 定義的 Action_xxxx 函數(shù)名的 xxx 部分
NSString * const kCTMediatorActionNativTo_NewsViewController = @"NativeToNewsViewController";
注:這篇寫的較早呼畸。作者前段時間也親自寫了篇教程:在現(xiàn)有工程中實施基于CTMediator的組件化方案 比這篇詳盡痕支,各位還是移步原 po 的教程吧……