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

前言

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

1.UCRuntimeKit:這個小工具主要是為了能夠利用字符串+runtime動態(tài)的調(diào)用方法.經(jīng)過了500多條單元測試,基本滿足所有的使用場景,安全,且支持向調(diào)用方拋出error,但不會crash.在這里它主要是為了向各個組件中的delegate轉(zhuǎn)發(fā)多參數(shù)方法用的.

2.UCAppDelegateReduce.這個小工具依賴上面的UCRuntimeKit來做消息轉(zhuǎn)發(fā).

實現(xiàn)原理

  • 1.先將項目中的delegate與框架中的UCAppDelegateRealize實現(xiàn)的22個方法進行交換,如果appdelegate沒實現(xiàn)這個方法則不會交換,交換完成后不影響之前的邏輯,依舊會先調(diào)用原先appdelegate的邏輯,如果這22個方法沒有包含你需要轉(zhuǎn)發(fā)給組件的方法的話支持擴展.

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

使用

可以利用cocoapod進行導入,pod 'UCAppDelegateReduce'

Objc中的使用

ObjcDemo

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

  • 2.在load類方法里進行下面的配置,就可以了

      + (void)load {
    
      UCAppDelegateMethodExchangeManager *manager = [UCAppDelegateMethodExchangeManager share];
      // sendMessageType 是位移枚舉,可以選擇自己想給子模塊派發(fā)的方法
      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.要轉(zhuǎn)發(fā)的Module中的appdelegate方法前要加@objc,否則不支持動態(tài)調(diào)用

  • 3.在load類方法里進行下面的配置,就可以了

      + (void)load {
      
      UCAppDelegateMethodExchangeManager *manager = [UCAppDelegateMethodExchangeManager share];
      
      // 這里Objc調(diào)用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是很靈活的,支持位移枚舉配置,配置后不會調(diào)用未配置的方法,另外manager的配置在app的生命周期中只應(yīng)該在最開始load的時候配置一次!配置完成后這里會解析,生成類似這樣的map,以代理方法名為key,需要轉(zhuǎn)發(fā)的類名集合為value,并將這個map緩存在內(nèi)存中,方便快速轉(zhuǎn)發(fā)給各個組件.

這樣你就可以把例如原先寫在appdelegate中的開屏配置,分享key配置,支付配置,push路由配置,3Dtouch等等直接寫在各自的模塊中了,這里的調(diào)用順序也是可以通過配置來決定的.

但是如果這個調(diào)用是異步的,例如組件B的一個功能依賴組件B的回調(diào),建議還是把這個寫在組件a的delegate實現(xiàn)里.

做完了這些你會發(fā)現(xiàn)你原來的delegate基本可以什么都不寫了,他已經(jīng)把業(yè)務(wù)分散到各個組件中去了.

UT

關(guān)于單元測試,這里基本只是測試了調(diào)用這個模塊的,轉(zhuǎn)發(fā)各個模塊都是手動測得,判斷參數(shù)能傳入到各個組件就沒有更深度的寫了,這里的單元測試確實不太好寫.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、你在項目中用過 runtime 嗎?舉個例子。 a、Method Swizzling動態(tài)交換方法實現(xiàn),實則交換...
    寫代碼的小農(nóng)民閱讀 1,439評論 0 4
  • iOS網(wǎng)絡(luò)架構(gòu)討論梳理整理中。。。 其實如果沒有APIManager這一層是沒法使用delegate的,畢竟多個單...
    yhtang閱讀 5,466評論 1 23
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,030評論 0 9
  • 最近一朋友正準備跳槽,就從各處搜索整理一些基礎(chǔ),便于朋友復習,也便于自己復習查看. 1. 回答person的ret...
    smile麗語閱讀 1,900評論 0 7
  • 1.最喜歡看可可睡覺的樣子,安安靜靜,一呼一吸。我隨意地親吻她,軟軟肉肉的臉蛋,真可愛。每天都看不膩,親不膩。 2...
    春娟Jane閱讀 156評論 0 1

友情鏈接更多精彩內(nèi)容