利用runtime來給組件化項目appdelegate減負

前言

本文主要依賴我寫的兩個工具git

1.UCRuntimeKit:這個小工具主要是爲了可以利用字符串+runtime動態的調用方法.通過了500多條單元測試,基本知足全部的使用場景,安全,且支持向調用方拋出error,但不會crash.在這裏它主要是爲了向各個組件中的delegate轉發多參數方法用的.github

2.UCAppDelegateReduce.這個小工具依賴上面的UCRuntimeKit來作消息轉發.swift

實現原理

  • 1.先將項目中的delegate與框架中的UCAppDelegateRealize實現的22個方法進行交換,若是appdelegate沒實現這個方法則不會交換,交換完成後不影響以前的邏輯,依舊會先調用原先appdelegate的邏輯,若是這22個方法沒有包含你須要轉發給組件的方法的話支持擴展.緩存

  • 2.當delegate接收到調用時,會自動來到UCAppDelegateRealize,這裏在會根據位移枚舉的配置來對各個組件調用,這個調用過程依賴UCRuntimeKit,十分安全,不會crash.安全

使用

能夠利用cocoapod進行導入,pod 'UCAppDelegateReduce'app

Objc中的使用

ObjcDemo框架

  • 1.新建一個Objc類,例如我這裏取名叫AppDelegateExchange異步

  • 2.在load類方法裏進行下面的配置,就能夠了工具

    + (void)load {
    
      UCAppDelegateMethodExchangeManager *manager = [UCAppDelegateMethodExchangeManager share];
      // sendMessageType 是位移枚舉,能夠選擇本身想給子模塊派發的方法
      UCAppDelegateConfigModel *model1 = [[UCAppDelegateConfigModel alloc] initWithModuleName:@"UCObjcModule1AppDelegate" sendMessageType:didFinishLaunchingWithOptions];
      UCAppDelegateConfigModel *model2 = [[UCAppDelegateConfigModel alloc] initWithModuleName:@"UCObjcModule2AppDelegate" sendMessageType:handleOpenURL | didFinishLaunchingWithOptions];
      
      [manager startExchangeMethodWithOriginalAppDelegateName:@"UCAppDelegate" newModuleAppDelegateConfigArray:@[model1, model2]];
      }
    複製代碼

Swift的使用

SwiftDemo單元測試

  • 1.新建一個Objc類,例如我這裏取名叫AppDelegateExchange

  • 2.要轉發的Module中的appdelegate方法前要加@objc,不然不支持動態調用

  • 3.在load類方法裏進行下面的配置,就能夠了

    + (void)load {
      
      UCAppDelegateMethodExchangeManager *manager = [UCAppDelegateMethodExchangeManager share];
      
      // 這裏Objc調用Swift須要加上相似命名空間的前綴,不然找不到這個Swift class
      NSString *swiftModule1Name = [UCMediatorParameterParser getObjcClassName:@"SwiftModule1AppDelegate"];
      // 支持位移枚舉
      UCAppDelegateConfigModel *model1 = [[UCAppDelegateConfigModel alloc] initWithModuleName:swiftModule1Name sendMessageType:didFinishLaunchingWithOptions];
      
      NSString *swiftModule2Name = [UCMediatorParameterParser getObjcClassName:@"SwiftModule2AppDelegate"];
      UCAppDelegateConfigModel *model2 = [[UCAppDelegateConfigModel alloc] initWithModuleName:swiftModule2Name sendMessageType:handleOpenURL | didFinishLaunchingWithOptions];
      
      NSString *originalDelegateName = [UCMediatorParameterParser getObjcClassName:@"AppDelegate"];
      [manager startExchangeMethodWithOriginalAppDelegateName:originalDelegateName newModuleAppDelegateConfigArray:@[model1, model2]];
      }
    複製代碼

UCAppDelegateConfigModel是很靈活的,支持位移枚舉配置,配置後不會調用未配置的方法,另外manager的配置在app的生命週期中只應該在最開始load的時候配置一次!配置完成後這裏會解析,生成相似這樣的map,以代理方法名爲key,須要轉發的類名集合爲value,並將這個map緩存在內存中,方便快速轉發給各個組件.

這樣你就能夠把例如原先寫在appdelegate中的開屏配置,分享key配置,支付配置,push路由配置,3Dtouch等等直接寫在各自的模塊中了,這裏的調用順序也是能夠經過配置來決定的.

可是若是這個調用是異步的,例如組件B的一個功能依賴組件B的回調,建議仍是把這個寫在組件a的delegate實現裏.

作完了這些你會發現你原來的delegate基本能夠什麼都不寫了,他已經把業務分散到各個組件中去了.

UT

關於單元測試,這裏基本只是測試了調用這個模塊的,轉發各個模塊都是手動測得,判斷參數能傳入到各個組件就沒有更深度的寫了,這裏的單元測試確實不太好寫.

相關文章
相關標籤/搜索