iOS組件化casa方案的我的理解

casa老師的方案主要是基於Mediator模式和Target-Action模式,中間採用了runtime來完成調用。swift

下面以Demo爲例,來分析一下組件化實施的方式。首先看一下Demo的項目結構:bash

CTMediator類就是中間件類,負責遠程調用和本地組件間調用的處理和分發。函數

#import <UIKit/UIKit.h>

extern NSString * const kCTMediatorParamsKeySwiftTargetModuleName;

@interface CTMediator : NSObject

+ (instancetype)sharedInstance;

// 遠程App調用入口
- (id)performActionWithUrl:(NSURL *)url completion:(void(^)(NSDictionary *info))completion;
// 本地組件調用入口
- (id)performTarget:(NSString *)targetName action:(NSString *)actionName params:(NSDictionary *)params shouldCacheTarget:(BOOL)shouldCacheTarget;
- (void)releaseCachedTargetWithTargetName:(NSString *)targetName;

@end
複製代碼

其中遠程調用函數performActionWithUrl:completion:是對url進行處理解析後轉化成本地調用。組件化

看一下本地調用函數的代碼實現:ui

NSString *swiftModuleName = params[kCTMediatorParamsKeySwiftTargetModuleName];
    
    // generate target
    NSString *targetClassString = nil;
    if (swiftModuleName.length > 0) {
        targetClassString = [NSString stringWithFormat:@"%@.Target_%@", swiftModuleName, targetName];
    } else {
        targetClassString = [NSString stringWithFormat:@"Target_%@", targetName];
    }
    NSObject *target = self.cachedTarget[targetClassString];
    if (target == nil) {
        Class targetClass = NSClassFromString(targetClassString);
        target = [[targetClass alloc] init];
    }

    // generate action
    NSString *actionString = [NSString stringWithFormat:@"Action_%@:", actionName];
    SEL action = NSSelectorFromString(actionString);
    
    if (target == nil) {
        // 這裏是處理無響應請求的地方之一,這個demo作得比較簡單,若是沒有能夠響應的target,就直接return了。實際開發過程當中是能夠事先給一個固定的target專門用於在這個時候頂上,而後處理這種請求的
        [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的notFound方法統一處理
        SEL action = NSSelectorFromString(@"notFound:");
        if ([target respondsToSelector:action]) {
            return [self safePerformAction:action target:target params:params];
        } else {
            // 這裏也是處理無響應請求的地方,在notFound都沒有的時候,這個demo是直接return了。實際開發過程當中,能夠用前面提到的固定的target頂上的。
            [self NoTargetActionResponseWithTargetString:targetClassString selectorString:actionString originParams:params];
            [self.cachedTarget removeObjectForKey:targetClassString];
            return nil;
        }
    }
複製代碼

首先獲取target實例。而後生成target要出發的消息SEL action,而後發送消息(調用函數)。url

DemoModule文件夾即表明一個具體的組件(模塊),下面簡稱AModule,Target-A類即這個組件(模塊)對外暴露的可調用方法(對外接口)的具體實現,方法的實現都是基於組件內。那麼當別的地方想調用AModule時怎麼處理呢?並非直接引用Target-A,若是這樣就與AModule耦合在了一塊兒,破壞了組件的獨立性。既然是Mediator模式,固然是有中間件,咱們看一下CTMediator+CTMediatorModuleAActions這個類。這裏使用了分類來擴展CTMediator,增長了AModule的對外接口,保證了AModule的獨立性。若是之後出現了BModule,只須要建立一個CTMediator+CTMediatorModuleBActions,來實現BModule的對外接口。spa

我的認爲casa的組件化方案整體是優於蘑菇街的組件化方案的。可是對蘑菇街URLProtocol的方式加以改造,使用runtime的方式調用,就跟casa的方案接近同樣了,你們能夠試一下。至於openURL的方式,若是隻支持本地調用,在Target-X中註冊URL,是否是也相似Target-Action模式呢。3d

若是個人文章對你有所幫助,請留言告訴我,Thanks!code

相關文章
相關標籤/搜索