三国杀武将|手游三国杀边锋版

首頁 >iOS開發

講解通過協議實現組件化解耦

2019-04-29 09:37 編輯: suiling 分類:iOS開發 來源:孟令超

GitHub地址:

https://github.com/mlcldh/LCLive

講解通過協議實現組件化解耦的直播demo。 現在是將各個組件代碼和主工程放到了一個Git工程里,當然實際應該是放到不同Git工程的。

主工程依賴這些組件。LCLive是主工程。 LCMediator是調度層中間件。 LCBase是基礎模塊,封裝公共類和方法。 LCWeb是h5、weex模塊。 LCChat是私信模塊。 LCMomment是朋友圈模塊。

Podfile如下:

platform :ios, '8.0'
use_frameworks!

source ' 

target 'LCLive' do

pod 'LCMediator', :path => '../LCMediator'
pod 'LCBase', :path => '../LCBase'
pod 'LCUser', :path => '../LCUser'
pod 'LCShare', :path => '../LCShare'
pod 'LCMe', :path => '../LCMe'
pod 'LCChat', :path => '../LCChat'
pod 'LCWeb', :path => '../LCWeb'
pod 'LCMoment', :path => '../LCMoment'
pod 'LCLaunch', :path => '../LCLaunch'

end

中間件是LCMediator,它里面定義了User、私信、Web、Moment等協議,供相應組件實現了和供其他組件調用。

圖片 8

通過NSClassFromString方法獲取到類后,寫代碼讓該類執行類方法時,Xcode不會給提示,畢竟Xcode無法只提供Class這一個類型就判斷出具體是那種類。既然不給提示,就要自己將代碼復制過去,然后編譯也沒問題。但如果復制成了其他類方法,只要這個類方法能夠引用到,編譯就不會報錯,這樣就會出問題了。這樣因為Xcode對類方法編譯不夠友好,將所有組件協議方法都寫成實例方法。

LCMediator的LCMediatorHeader里通過傳入的組件協議返回實現該協議的類的實例。 方法LCModuleInstanceFromProtocol獲取到的也就只是實例對象。調用組件協議實例時,不需要提前注冊,LCModuleInstanceFromProtocol內部做了懶加載處理。

/**根據傳入的組件協議返回實現該協議的類的對象*/
NS_INLINE id LCModuleInstanceFromProtocol(Protocol *protocol) {
    NSString *className = NSStringFromProtocol(protocol);
    Class aClass = NSClassFromString(className);
//    NSLog(@"class %@,%@",className,aClass);
    static NSMutableDictionary *modulesDictionary = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        modulesDictionary = [NSMutableDictionary dictionary];
    });
    id module = modulesDictionary[className];
    if (!module) {
        module = [[aClass alloc]init];
        modulesDictionary[className] = module;
    }
    if ([module conformsToProtocol:protocol]){
        return module;
    }
    return nil;
}

#define LCModuleInstance(module,LCModuleProtocol) id module = LCModuleInstanceFromProtocol(@protocol(LCModuleProtocol));
#define LCGetModuleInstance(LCModuleProtocol) ((id)(LCModuleInstanceFromProtocol(@protocol(LCModuleProtocol))))
/**用戶信息模塊*/
@protocol LCUserModule /**用戶id*/
- (NSString *)userId;
/**token*/
- (NSString *)token;
/**用戶昵稱*/
- (NSString *)nickname;
/**用戶頭像url地址*/
- (NSString *)avatarUrlString;

@end
@interface LCUserModule : [email protected]
@implementation LCUserModule

- (NSString *)userId {
    return @"abc123100";
}
- (NSString *)token {
    return @"qwe007what";
}
- (NSString *)nickname {
    return @"李明";
}
- (NSString *)avatarUrlString {
    return @"https://ss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=3843887011,4044287239&fm=173&app=25&f=JPEG?w=218&h=146&s=F81821D40331ABCC106BAA8003008088";
//    return @"https://avatar.csdn.net/7/5/6/1_mlcldh.jpg?1532075030";
}

@end
_nicknameLabel.text = [LCGetModuleInstance(LCUserModule) nickname];

LCWeb是h5、weex模塊。 LCWebModule里面實現協議提供跳轉到H5的方法。

@implementation LCWebModule

- (void)pushWebViewControllerWithUrlString:(NSString *)urlString fromViewController:(UIViewController *)viewController {
    LCWebViewController *webVC = [[LCWebViewController alloc]init];
    webVC.urlString = urlString;
    [viewController.navigationController pushViewController:webVC animated:YES];
}

@end

LCChat是私信模塊。LCChatModule提供讀取消息未讀數和跳轉到單例詳情的方法。

@implementation LCChatModule

- (UIViewController *)sessionListViewController {
    LCSessionListViewController *vc = [[LCSessionListViewController alloc]init];
    return vc;
}
- (NSUInteger)ureandCount {
    return 3;
}
- (void)pushUserChatViewControllerWithUserId:(NSString *)userId fromViewController:(UIViewController *)viewController {
    LCUserChatViewController *userChatVC = [[LCUserChatViewController alloc]init];
    [viewController.navigationController pushViewController:userChatVC animated:YES];
}

@end

LCWeb是h5、weex模塊。 LCWebModule里面實現協議提供跳轉到H5的方法。

@implementation LCWebModule

- (void)pushWebViewControllerWithUrlString:(NSString *)urlString fromViewController:(UIViewController *)viewController {
    LCWebViewController *webVC = [[LCWebViewController alloc]init];
    webVC.urlString = urlString;
    [viewController.navigationController pushViewController:webVC animated:YES];
}

@end

LCChat是私信模塊。LCChatModule提供讀取消息未讀數和跳轉到單例詳情的方法。

@implementation LCChatModule

- (UIViewController *)sessionListViewController {
    LCSessionListViewController *vc = [[LCSessionListViewController alloc]init];
    return vc;
}
- (NSUInteger)ureandCount {
    return 3;
}
- (void)pushUserChatViewControllerWithUserId:(NSString *)userId fromViewController:(UIViewController *)viewController {
    LCUserChatViewController *userChatVC = [[LCUserChatViewController alloc]init];
    [viewController.navigationController pushViewController:userChatVC animated:YES];
}

@end

優點:

  1. 組件間的調用更為方便。

  2. 解耦代碼量少,實現方便,以后維護也方便。

  3. 協議方法改變后,編譯就會報錯,避免代碼修改遺漏。

  4. 協議方法未實現的話,會報編譯警告。

  5. 方法查找容易,調用高效。

  6. 不需要注冊即可調用。

缺點:

  1. 組件的方法調用分散。

  2. 內存中維護映射表。

  3. 協議方法有可能未實現,調用會導致崩潰。

使用注意事項:

  1. 組件協議的方法都要寫成實例方法,不要寫成類方法。

  2. 組件協議的方法都要實現,因為調用時不會去判斷方法有沒有實現。

  3. 獲取組件協議實現的實例對象,只能使用LCModuleInstance(module,LCModuleProtocol) 或LCGetModuleInstance(LCModuleProtocol)這兩個個宏,從而避免直接使用LCModuleInstanceFromProtocol獲取到實現類,讓實現類執行了其并不遵守的協議方法。

  4. 組件協議實現的實例對象只是用來負責組件通信的,不要用它們來存儲其他東西,因為這些事例對象一直不會去釋放,存儲太多東西,容易出現內存占用過多的問題。

搜索CocoaChina微信公眾號:CocoaChina
微信掃一掃
訂閱每日移動開發及APP推廣熱點資訊
公眾號:
CocoaChina
我要投稿   收藏文章
上一篇:讀URLNavigator源碼
下一篇:談談 iOS 網絡層設計
我來說兩句
發表評論
您還沒有登錄!請登錄注冊
所有評論(0

綜合評論

相關帖子

sina weixin mail 回到頂部
三国杀武将