本來是要寫我自己用的router的,但是現(xiàn)在這個(gè)有點(diǎn)落后了, 所以這篇文章主要說下CTMediator這個(gè)router的設(shè)計(jì),我覺得這個(gè)比較符合當(dāng)下我對(duì)router理解。
它主要有一個(gè)類CTMediator,里面有3個(gè)方法,performActionWithUrl,performTarget和releaseCachedTargetWithTargetName前2個(gè)的作用主要是返回controller,后一個(gè)是清除緩存。performActionWithUrl是根據(jù)url解析出所需要的數(shù)據(jù)在調(diào)用performTarget生成controller,下面來看下performTarget這個(gè)主要方法:
- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget
{
NSString *targetClassString = [NSString stringWithFormat:@"Target_%@", targetName];
NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName];
Class targetClass;
NSObject *target = self.cachedTarget[targetClassString];
if (target == nil) {
targetClass = NSClassFromString(targetClassString);
target = [[targetClass alloc] init];
}
SEL action = NSSelectorFromString(actionString);
if (target == nil) {
// 這里是處理無響應(yīng)請求的地方之一,這個(gè)demo做得比較簡單,如果沒有可以響應(yīng)的target,就直接return了。實(shí)際開發(fā)過程中是可以事先給一個(gè)固定的target專門用于在這個(gè)時(shí)候頂上,然后處理這種請求的
[self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params];
return nil;
}
if (shouldCacheTarget) {
self.cachedTarget[targetClassString] = target;
}
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target params:params];
} else {
// 有可能target是Swift對(duì)象
actionString = [NSString stringWithFormat:@"Action_%@WithParams:", actionName];
action = NSSelectorFromString(actionString);
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target params:params];
} else {
// 這里是處理無響應(yīng)請求的地方,如果無響應(yīng),則嘗試調(diào)用對(duì)應(yīng)target的notFound方法統(tǒng)一處理
SEL action = NSSelectorFromString(@"notFound:");
if ([target respondsToSelector:action]) {
return [self safePerformAction:action target:target params:params];
} else {
// 這里也是處理無響應(yīng)請求的地方,在notFound都沒有的時(shí)候,這個(gè)demo是直接return了。實(shí)際開發(fā)過程中,可以用前面提到的固定的target頂上的。
[self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params];
[self.cachedTarget removeObjectForKey:targetClassString];
return nil;
}
}
}
}
targetName就是調(diào)用接口的Object,actionName就是調(diào)用方法的SEL,params是參數(shù),shouldCacheTarget代表是否需要緩存,如果需要緩存就把target存起來,Key是targetClassString,Value是target。
通過這種方式進(jìn)行改造的,外面調(diào)用的方法都很統(tǒng)一,都是調(diào)用performTarget: action: params: shouldCacheTarget:。第三個(gè)參數(shù)是一個(gè)字典,這個(gè)字典里面可以傳很多參數(shù),只要Key-Value寫好就可以了。處理錯(cuò)誤的方式也統(tǒng)一在一個(gè)地方了,target沒有,或者是target無法響應(yīng)相應(yīng)的方法,都可以在Mediator這里進(jìn)行統(tǒng)一出錯(cuò)處理。
但是在實(shí)際開發(fā)過程中,不管是界面調(diào)用,組件間調(diào)用,在Mediator中需要定義很多方法。于是做作者又想出了建議我們用Category的方法,對(duì)Mediator的所有方法進(jìn)行拆分,這樣就就可以不會(huì)導(dǎo)致Mediator這個(gè)類過于龐大了。所以可以看下demo中的#import "CTMediator+CTMediatorModuleAActions.h"是怎么管理的。
代碼地址:https://github.com/casatwy/CTMediator
參考文章:https://lpd-ios.github.io/2017/02/26/iOS-Router/