TinyPart:面向協議的 iOS 模組化框架(OC)
TinyPart
TinyPart是一個由Objective-C編寫的面向協議的iOS模組化框架,同時它還支援URL路由和模組間通訊機制。
安裝
cocoapods
pod 'TinyPart'
特點
-
面向協議。TinyPart中模組和服務都是面向協議的。服務面向協議的好處在於對於介面維護比較友好,任何介面的變動在編譯時都是可見的,但是大型專案有可能會面臨大量需要維護的協議,這也是不可忽視的缺點。
-
動態化。TinyPart中模組和服務的註冊都是在執行時完成的,可以根據具體需要調整模組的註冊和啟動時間,非同步啟動模組對於優化APP首屏載入時間會有幫助。
-
路由服務。我們知道面向協議的服務雖然對於介面維護比較方便,但是模組間相互呼叫各自服務,是需要知道對方協議的,這樣最後可能會導致所有的協議需要暴露給所有的模組。比如現在有10個模組每個模組有1個服務協議,在上述情況下每個模組需要知道另外9個模組的協議,這相當於每個協議都被@import了9次,所有協議總共將會被@import 9*10=90次,這對於想做完全程式碼隔離的模組化來說是個噩夢。通過路由服務則很好地平衡了模組間呼叫和依賴問題,順便也解決了跨APP跳轉的問題。
-
URL路由。在路由基礎上,只需要再增加簡單的1到2行程式碼就可以實現通過APPScheme的URL路由機制。
-
多級模組有向通訊。一般來說,完全去耦合的模組間通訊方案大概是兩種:URL和通知
NSNotification
。URL解決了模組間服務相互呼叫的問題,但是如果想要通過URL實現一個觀察者模式則會變得非常複雜。這時候大家可能會偏向於選擇通知,但是由於通知是全域性性的,這樣會導致任何一條通知可能會被APP內任何一個模組所使用,久而久之這些通知會變得難以維護。所謂 多級模組有向通訊 ,則是在
NSNotification
基礎上對通知的傳播方向進行了限制,底層模組對上層模組的通知稱為 廣播Broadcast
,上層模組對底層模組或者同層模組的通知稱為 上報Report
。這樣做有兩個好處:一方面更利於通知的維護,另一方面可以幫助我們劃分模組層級,如果我們發現有一個模組需要向多個同級模組進行Report
那麼這個模組很有可能應該被劃分到更底層的模組。
架構說明
用法
初始化
- 繼承 TPAppDelegate,初始化TPContext
#import "TinyPart.h" @interface AppDelegate : TPAppDelegate @property (strong, nonatomic) UIWindow *window; @end @implementation AppDelegate @synthesize window; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [TPMediator sharedInstance].deleagate = self; [TPContext sharedContext].launchOptions = launchOptions; [TPContext sharedContext].application = application; [TinyPart sharedInstance].context = [TPContext sharedContext]; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end
模組Module
- 定義並註冊一個模組
#import "TinyPart.h" @interface TestModule1 : NSObject <TPModuleProtocol> @end @implementation TestModule1 TP_MODULE_AUTO_REGISTER // 自動註冊模組,動態註冊模組 TP_MODULE_ASYNC// 非同步啟動模組,優化開屏效能 TP_MODULE_PRIORITY(1)// 模組啟動優先順序,優先順序高的先啟動 TP_MODULE_LEVEL(TPModuleLevelBasic)// 模組級別:基礎模組 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { return YES; } - (void)moduleDidLoad:(TPContext *)context { switch (context.env) { case TPRunningEnviromentTypeDebug: { NSLog(@"%@", @"TestModule1 moduleDidLoad: debug"); break; } case TPRunningEnviromentTypeRelease: { NSLog(@"%@", @"TestModule1 moduleDidLoad: release"); break; } } } @end
服務Service用法
- 定義並註冊一個服務Service 。Service可自定義單例模式或多例模式。
#import "TPServiceProtocol.h" @protocol TestModuleService1 <TPServiceProtocol> - (void)function1; @end @interface TestModuleService1Imp : NSObject <TestModuleService1> @end @implementation TestModuleService1Imp TPSERVICE_AUTO_REGISTER(TestModuleService1) // 自動註冊服務 - (void)function1 { NSLog(@"%@", @"TestModuleService1 function1"); } @end
- 訪問服務Sevice
id<TestModuleService1> service1 = [[TPServiceManager sharedInstance] serviceWithName:@"TestModuleService1"]; [service1 function1];
路由Router用法
- 定義並註冊一個路由Router
#import "TPRouter.h" @interface TestRouter : TPRouter @end #import "TinyPart.h" @implementation TestRouter TPROUTER_AUTO_REGISTER// 自動註冊路由 // APP身份驗證,需要實現TPMediatorDelegate中的身份驗證回撥 TPRouter_AUTH_REQUIRE(@"action1", @"action2") TPROUTER_METHOD_EXPORT(action1, { NSLog(@"TestRouter action1 params=%@", params); return nil; }); TPROUTER_METHOD_EXPORT(action2, { NSLog(@"TestRouter action2 params=%@", params); return nil; }); @end
- 使用路由Router
[[TPMediator sharedInstance] performAction:@"action1" router:@"Test" params:@{}];
URL路由
- 配置configPlistFile 。
TinyPart.bundle/TinyPart.plist
是context.configPlistFileName
的預設路徑,因此即使沒有下面第二行程式碼也是OK的。
TPContext *context = [TPContext sharedContext]; context.configPlistFileName = @"TinyPart.bundle/TinyPart.plist"; [TinyPart sharedInstance].context = context;
- 新建
TinyPart.bundle/TinyPart.plist
,並註冊一條 URL Scheme
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>APPURLSchemes</key> <array> <string>tinypart</string> </array> </dict> </plist>
- 定義一條URL路由規則 。在已有的
TestRouter
基礎上,我們只需要新建一個TPMediator+Test
的擴充套件。
@implementation TPMediator (Test) + (void)load { // 宣告TestRouter對應的Host TPURLHostForRouter(@"com.tinypart.test", TestRouter) // tinypart://com.tinypart.test // 宣告TestRouter中action1對應的Path TPURLPathForActionForRouter(@"/action1", action1, TestRouter);// tinypart://com.tinypart.test/action1 } @end
- 使用URL路由
NSURL *url = [NSURL URLWithString:@"tinypart://com.tinypart.test/action1?id=1&name=tinypart"]; [[TPMediator sharedInstance] openURL:url];
有向通訊
- 傳送 。這裡注意前面提到的,底層模組對上層模組的通知稱為 廣播
Broadcast
,上層模組對底層模組或者同層模組的通知稱為 上報Report
。模組級別分為 Basic、Middle、Topout 三個級別。
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]; // Observer銷燬後自動釋放 [center1 addObserver:self selector:@selector(testNotification:) name:@"report_notification_from_TestModule2" object:nil];
參考專案
Hive" rel="nofollow,noindex" target="_blank"> BeeHive
開源許可證
TinyPart is available under the MIT license. See the LICENSE file for more info.