亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > iOS > 正文

iOS模塊化開發淺析

2019-10-21 18:41:21
字體:
來源:轉載
供稿:網友

背景:由于目前所在公司的iOS項目的依賴管理是比較原始的狀態,但是APP功能又是越來越復雜的,這就帶來的很多問題,比如開發時編譯時間過長、模塊間耦合嚴重、模塊依賴混亂等。最近又聽說這個項目中的部分功能可能需要獨立出一個新APP,本著“Don't repeat yourself”的原則,我們試著抽離出原項目中的各個模塊,并在新的APP中集成這些模塊。

最近算是初步完成了新APP的模塊化,也算是從中總結了一些經驗拿出來分享一下。同時也完成了一個模塊化框架TinyPart歡迎star。

模塊劃分

做模塊化還是要結合實際業務,對目前APP的功能做一個模塊劃分,在劃分模塊的時候還需要關注模塊之間的層級。

比如說,在我們項目中,模塊被分成了3個層級:基礎層、中間層、業務層?;A層模塊比如像網絡框架、持久化、Log、社交化分享這樣的模塊,這一層的模塊我們可以稱之為組件,具有很強的可重用性。中間層模塊可以有登錄模塊、網絡層、資源模塊等,這一層模塊有一個特點是它們依賴著基礎組件但又沒有很強的業務屬性,同時業務層對這層模塊的依賴是很強的。業務層模塊,就是直接和產品需求對應的模塊了,比如類似朋友圈、直播、Feeds流這樣的業務功能了。

代碼隔離

模塊化首先要做的是代碼層面上獨立,任意一個基礎模塊都是可以獨立編譯的,底層模塊絕對不能有對上層模塊的代碼依賴,還要確保未來也不會再出現這樣的代碼。

在這里我們選擇使用CocoaPods來確保模塊間代碼隔離,基礎和中間層模塊是一定會做成標準的私有pods組件,加入到私有pods倉庫。業務層的模塊,則不一定非要加到私有pods倉庫中,也可以使用submodule + local pods的方案。這樣做有兩個原因:其一是業務模塊的改動往往比較頻繁,如果是標準的私有pods組件則需要頻繁的操作pod install或者pod update;其二是如果是local pod會直接引用對應倉庫的源文件,在主工程對pods工程下業務模塊的改動就是直接對其git倉庫的改動,沒有了頻繁的pod repo push和pod install操作。

依賴管理

選擇使用CocoaPods另外一個重要原因就是,可以通過它來管理模塊間的依賴,之前項目各個功能之所以難以復用的重要原因之一就是沒有聲明依賴。這里的依賴不僅僅是A模塊依賴B模塊這樣的事情,還可以是A模塊運行需要的所有工程配置,比如A模塊工程需要添加一個GCC_PREPROCESSOR_DEFINITIONS預處理宏才能正常編譯。因此,個人認為模塊依賴聲明非常重要,即便沒有像CocoaPods這樣的管理工具,也應該有相關文檔來說明每個內部模塊或者SDK的依賴。

CocoaPods的方便之處就在于你必須把你模塊的依賴列出來,否則是無法通過pod spec lint過程的,并且所有的依賴項也都是必須是pods倉庫。除此以外,依賴的集成也是自動化的,CocoaPods可以自動地添加工程配置和依賴組件。

模塊集成

在完成上述兩個步驟以后,模塊化工程的構建工作基本就結束了,接下來我們探討一下如何在工程中更好地使用這些模塊。為此我們寫了一個組件化的開源方案 TinyPart。

一般來說,模塊初始化需要在APP啟動或者UI初始化附近的時機來完成,有時候各個模塊的啟動順序可能也是有講究的,這些初始化邏輯我們往往會加入到AppDelegate這個類里。過一段時間我們會發現,AppDelegate這個類變得臃腫不堪,邏輯復雜,難以維護。在TinyPart中,Module的聲明協議包含了UIApplicationDelegate,這就意味著每一個模塊都可以實現有一套自己的UIApplicationDelegate協議,并且它們之間調用順序是可以自定義的。

@interface TPLShareModule : NSObject <TPModuleProtocol>@end@implementation TPLShareModuleTP_MODULE_ASYNCTP_MODULE_PRIORITY(TPLSHARE_MODULE_PRIORITY)- (void)moduleDidLoad:(TPContext *)context {  [WXApi registerApp:APPID];}- (BOOL)application:(UIApplication *)application      openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication     annotation:(id)annotation {  return [WXApi handleOpenURL:url delegate:self];}- (BOOL)application:(UIApplication *)app      openURL:(NSURL *)url      options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {  return [WXApi handleOpenURL:url delegate:self];}@end

上面的代碼是一個微信社交分享模塊的初始化內容,同時實現了微信分享所要求的UIApplicationDelegate中的方法。

通信

消息

在面向對象中,消息是一個十分重要的概念,它是對象之前通信的重要方式。但是,在OC中如果想要向一個對象發消息,正常做法就是將改對象類的頭文件import進來,這樣我們就能夠寫出[aInstance method]這樣的代碼了。

然而在模塊化中,我們并不希望模塊與模塊之間相互引用各自的類文件,但是又想要實現通信,那怎么辦呢?通過協議來完成。我們知道OC是一個動態語言,方法的調用過程其實是動態的,頭文件中消息方法的聲明只是為了通過編譯前的靜態檢查。也就是說,我們只要寫一個協議來告訴編譯器有這么一個方法就可以了,至于實際上究竟有沒有這個方法是在消息發過去以后就知道了。既然OC有這個特性,我們甚至可以直接通過類名和方法名向一個對象發送消息,這其實就是網上大部分組件化路由的實現機制。

因此在TinyPart中我們既提供了協議和路由兩種模式來調用模塊內的服務。

@protocol TestModuleService1 <TPServiceProtocol>- (void)function1;@end@interface TestModuleService1Imp : NSObject <TestModuleService1>@end@implementation TestModuleService1ImpTPSERVICE_AUTO_REGISTER(TestModuleService1) // Service will be registered in "+load" method- (void)function1 {  NSLog(@"%@", @"TestModuleService1 function1");}@end

上面的代碼中,我們定義了一個服務的協議。

#import "TestModuleService1.h"id<TestModuleService1> service1 = [[TPServiceManager sharedInstance] serviceWithName:@"TestModuleService1"];[service1 function1];

這里我們只需要import上述協議的頭文件,然后就可以向TestModuleService1發消息了。

我們看到上述的跨模塊調用方案中,只需要暴露一個協議文件就可以了,下面我們再看一下如何用路由的方式來做到完全不暴露任何頭文件。

#import "TPRouter.h"@interface TestRouter : TPRouter@end@implementation TestRouterTPROUTER_METHOD_EXPORT(action1, {  NSLog(@"TestRouter action1 params=%@", params);  return nil;});TPROUTER_METHOD_EXPORT(action2, {  NSLog(@"TestRouter action2 params=%@", params);  return nil;});@end

在這里我們參考了ReactNative的方案,通過一個TPROUTER_METHOD_EXPORT宏來定義一個可供調用的路由服務,同時可以傳一個params參數進了。然后我們再來調用這個路由。

[[TPMediator sharedInstance] performAction:@"action1" router:@"Test" params:@{}];

通知

除了上面提到的兩種普通的模塊通信方案,我們發現在項目中經常會有跨模塊的NSNotification,對于這樣的觀察者模式使用NSNotification來實現是最便捷的方式了。盡管NSNotification可以做到模塊間解耦,但是對于通知的管理過于松散會導致散落在各個模塊的NSNotification邏輯變得十分復雜,因此我們為TinyPart增加了一種有向通信的方案。

所謂有向通信,則是在NSNotification基礎上對通知的傳播方向進行了限制,底層模塊對上層模塊的通知稱為廣播Broadcast,上層模塊對底層模塊或者同層模塊的通知稱為上報Report。這樣做有兩個好處:一方面更利于通知的維護,另一方面可以幫助我們劃分模塊層級,如果我們發現有一個模塊需要向多個同級模塊進行Report那么這個模塊很有可能應該被劃分到更底層的模塊。

用法同NSNotification類似,只不過創建通知的方法是一個鏈式調用,大概就是這樣:

// 發送TPNotificationCenter *center2 = [TestModule2 tp_notificationCenter];[center2 reportNotification:^(TPNotificationMaker *make) {  make.name(@"report_notification_from_TestModule2");} targetModule:@"TestModule1"];  [center2 broadcastNotification:^(TPNotificationMaker *make) {  make.name(@"broadcast_notification_from_TestModule2").userInfo(@{@"key":@"value"}).object(self);}];// 接收TPNotificationCenter *center1 = [TestModule1 tp_notificationCenter];[center1 addObserver:self selector:@selector(testNotification:) name:@"report_notification_from_TestModule2" object:nil];


注:相關教程知識閱讀請移步到IOS開發頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线成人免费网站| 欧美激情网站在线观看| 欧美成人全部免费| 欧美日韩激情美女| 热99精品只有里视频精品| 亚洲国产精品成人va在线观看| 日韩中文字幕国产精品| 国产午夜精品免费一区二区三区| 美女精品视频一区| 欧美精品久久久久久久久久| 欧美精品一区二区三区国产精品| 精品国产欧美一区二区五十路| 这里只有精品丝袜| 社区色欧美激情 | 91在线高清视频| 日韩欧美精品网址| 亚洲成人性视频| 国产精品91久久| www.精品av.com| 狠狠综合久久av一区二区小说| 精品美女久久久久久免费| 国产视频精品久久久| www.欧美视频| 亚洲成年人在线| 国产精品一区二区三区免费视频| 久久精品国产96久久久香蕉| 国产精品旅馆在线| 国产精品99久久久久久白浆小说| 亚洲免费电影在线观看| 欧美老少配视频| 亚洲自拍在线观看| 国产成人精品999| 亚洲美女在线看| 久久久国产精彩视频美女艺术照福利| 日韩中文字幕视频在线| 国产美女精品免费电影| 亚洲视频在线看| 亚洲精品一区二区三区不| 亚洲天堂网站在线观看视频| 成人在线一区二区| 亚洲欧美国产va在线影院| 亚洲级视频在线观看免费1级| 在线成人免费网站| 亚洲一区二区三区777| 91久久国产婷婷一区二区| 高清在线视频日韩欧美| 久久久国产精品免费| 91精品国产91久久久| 欧美性黄网官网| 亚洲天堂成人在线视频| 国产精品日日摸夜夜添夜夜av| 欧美国产精品日韩| 不卡av电影在线观看| 国产日韩精品视频| 久久影院模特热| 亚洲最大福利视频| 日韩在线观看免费| 欧美在线视频导航| 欧美在线免费看| 成人免费视频a| 亚洲一区二区国产| 奇米成人av国产一区二区三区| 国产a∨精品一区二区三区不卡| 国产精品无码专区在线观看| 国产美女久久精品| 国产精品午夜国产小视频| 久久99精品久久久久久青青91| 亚洲va码欧洲m码| 欧美激情亚洲国产| 这里只有精品视频在线| 精品久久久久久久久久久| 久久久久久久久爱| 国产精品爽爽爽爽爽爽在线观看| 91在线免费观看网站| 成人xvideos免费视频| 色www亚洲国产张柏芝| 国产色婷婷国产综合在线理论片a| 久久久精品国产| 日韩精品极品在线观看| 国产精品丝袜久久久久久高清| 欧美日韩亚洲网| 欧美美最猛性xxxxxx| 日韩精品免费看| 久久精品成人欧美大片古装| 成人久久久久久| 精品亚洲男同gayvideo网站| 日韩精品黄色网| 亚洲xxxx在线| 亚洲国产精品热久久| 亚洲精品久久视频| 欧美性xxxxx极品| 欧美日韩国产123| 成人深夜直播免费观看| 美日韩精品免费视频| www.日本久久久久com.| 亚洲精品久久7777777| 欧美高清无遮挡| 国产成+人+综合+亚洲欧洲| 91视频-88av| 色噜噜狠狠色综合网图区| 国产精品午夜国产小视频| 国产精品久在线观看| 91av视频在线播放| 97香蕉久久夜色精品国产| 成人免费观看49www在线观看| 国产精品久久久久久久美男| 欧美激情第6页| 亚洲欧美国产精品专区久久| 欧美日韩国产丝袜美女| 91久久国产精品| www.色综合| 国产不卡视频在线| 久久免费视频这里只有精品| 国产精品xxx视频| 九色精品免费永久在线| 日韩av综合网站| 日韩美女在线播放| 国产一区二区三区视频| 国产成人精品999| 亚洲欧美激情精品一区二区| 性金发美女69hd大尺寸| 日韩中文字幕在线视频| 亚洲a一级视频| 国内久久久精品| 国产婷婷色综合av蜜臀av| 日韩中文有码在线视频| 国产欧美精品久久久| 精品无人区太爽高潮在线播放| 欧美日韩国产精品专区| 欧美插天视频在线播放| 精品福利在线观看| 久久在线观看视频| 狠狠躁天天躁日日躁欧美| 日韩经典中文字幕在线观看| 日韩高清欧美高清| 精品美女永久免费视频| 精品国模在线视频| 久久精品国产亚洲精品| 亚洲精品av在线| 国产欧美日韩免费看aⅴ视频| 伊人伊人伊人久久| 中文字幕亚洲欧美一区二区三区| 亚洲 日韩 国产第一| 亚洲第一色中文字幕| 日韩国产激情在线| 国产视频综合在线| 九九热99久久久国产盗摄| 久久久国产精品免费| 不卡毛片在线看| 欧美激情xxxx| 亚洲国产精彩中文乱码av| 欧美精品久久久久久久久| 欧美性猛交xxxx乱大交3| 国产精品69久久| 欧美专区日韩视频| 欧美一区二区三区精品电影| 亚洲人午夜精品免费| 久久久久久网站| 亚洲国产私拍精品国模在线观看| 国产极品jizzhd欧美| 亚洲欧美国产精品va在线观看| 国产一区二区在线免费视频| 欧美高清在线视频观看不卡| 成人久久久久爱|