mPaaS iOS 架構源自支付寶用戶端的開發架構,基於 Framework 的設計思想,將業務隔離成相對獨立的模組,並著力追求模組與模組之間高內聚、低耦合。
mPaaS iOS 架構直接接管應用的生命週期,負責整個應用啟動託管、應用生命週期管理、處理與分發 UIApplication 的代理事件、統一管理各業務模組(微應用和服務)等。
本文將對 mPaaS iOS 架構進行詳細的介紹。
啟動託管
通過程式 main 函數的替換,直接接管應用的生命週期,整個啟動的過程如下:
main -> DFClientDelegate -> 開啟 Launcher 應用
應用生命週期管理
mPaaS 架構接入之後,完全替代了 AppDelegate 的角色,整個應用的生命週期由架構進行管理,但是使用者依然可以實現應用生命週期各個階段對應的代理方法,UIApplicationDelegate 中的所有代理方法,架構都提供了等價的接入方式,只需要在 Category 中覆蓋對應的方法即可。
架構提供的生命週期方法聲明如下,具體內容可以查看 DTFrameworkInterface.h
檔案。
/**
* 架構有一些自己的初始化邏輯在didFinishLaunching裡需要實現,但會在執行之前回調該方法。
*/
- (void)application:(UIApplication *)application beforeDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
/**
* 架構回調該方法,讓接入應用可以接管自己的didFinishLaunching邏輯。
* 並且當返回DTFrameworkCallbackResultReturnYES或DTFrameworkCallbackResultReturnNO時,直接給系統返回,不再執行接下來的邏輯。
* 這個方法在架構啟動BootLoader前回調,應用可以通過返回DTFrameworkCallbackResultReturnYES或DTFrameworkCallbackResultReturnNO讓架構提前退出,不運行預設的BootLoader。
* 使用架構內部的預設實現即可,通常不需要覆蓋。
*
* @return 是繼續讓架構執行,還是直接給系統返回YES或NO
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application handleDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
/**
* 架構有一些自己的初始化邏輯在didFinishLaunching裡需要實現,但會在所有邏輯完成後回調該方法。
*/
- (void)application:(UIApplication *)application afterDidFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
/**
* 架構會率先回調該方法,讓接入應用可以預先處理通知訊息。
* 當返回DTFrameworkCallbackResultContinue時,架構會把通知訊息通過UIApplicationDidReceiveRemoteNotification廣播給全域監聽者。並調用completionHandler(UIBackgroundFetchResultNoData)。
* 當返回DTFrameworkCallbackResultReturn時,表示接入應用已經完全處理完通知訊息,架構中止執行之後的邏輯。
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
/**
* 架構會率先回調該方法,讓接入應用可以預先處理通知訊息。
* 當返回DTFrameworkCallbackResultContinue時,架構會把通知訊息通過UIApplicationDidReceiveLocalNotification廣播給全域監聽者。
* 當返回DTFrameworkCallbackResultReturn時,表示接入應用已經完全處理完通知訊息,架構中止執行之後的邏輯。
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
/**
* 架構會率先回調該方法,讓接入應用可以預先處理通知訊息。
* 當返回DTFrameworkCallbackResultContinue時,架構會把通知訊息通過UIApplicationDidReceiveLocalNotification廣播給全域監聽者。並調用completionHandler()。
* 當返回DTFrameworkCallbackResultReturn時,表示接入應用已經完全處理完通知訊息,架構中止執行之後的邏輯。
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler;
/**
* 架構會率先回調該方法,讓接入應用可以拿到deviceToken。
* 當返回DTFrameworkCallbackResultContinue時,架構會把deviceToken通過UIApplicationDidRegisterForRemoteNotifications廣播給全域監聽者。
* 當返回DTFrameworkCallbackResultReturn時,表示接入應用已經完全處理完,架構中止執行之後的邏輯。
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
/**
* 當取deviceToken失敗時,架構率先回調該方法。
* 當返回DTFrameworkCallbackResultContinue時,架構繼續執行,目前無其它邏輯。
* 當返回DTFrameworkCallbackResultReturn時,架構中止之後的邏輯,目前無其它邏輯。
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
/**
* 架構會先給分享組件(如果有,並且shouldAutoactivateShareKit返回YES)通知,如果分享組件處理不了,再回調該方法,由接入應用處理openURL。
* 當返回DTFrameworkCallbackResultReturnYES或DTFrameworkCallbackResultReturnNO時,架構直接給系統返回,不再執行接下來的邏輯。
* 當返回DTFrameworkCallbackResultContinue時,繼續由架構處理URL,並分發給SchemeHandler等類來處理。
*
* 這個方法相比系統方法,多了一個newURL參數,允許應用在處理後,返回一個不同的url。如果函數整體返回DTFrameworkCallbackResultContinue,並且給newURL賦值,架構會使用新的URL來做後續處理。
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application openURL:(NSURL *)url newURL:(NSURL **)newURL sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
/**
* 架構率先回調該方法。
* 當返回DTFrameworkCallbackResultContinue時,架構繼續執行,目前無其它邏輯。
* 當返回DTFrameworkCallbackResultReturn時,架構中止之後的邏輯,目前無其它邏輯。
*/
- (DTFrameworkCallbackResult)applicationWillResignActive:(UIApplication *)application;
/**
* 架構率先回調該方法。
* 當返回DTFrameworkCallbackResultContinue時,架構繼續執行,目前無其它邏輯。
* 當返回DTFrameworkCallbackResultReturn時,架構中止之後的邏輯,目前無其它邏輯。
*/
- (DTFrameworkCallbackResult)applicationDidEnterBackground:(UIApplication *)application;
/**
* 架構率先回調該方法。
* 當返回DTFrameworkCallbackResultContinue時,架構繼續執行,目前無其它邏輯。
* 當返回DTFrameworkCallbackResultReturn時,架構中止之後的邏輯,目前無其它邏輯。
*/
- (DTFrameworkCallbackResult)applicationWillEnterForeground:(UIApplication *)application;
/**
* 架構先回調該方法。
* 當返回DTFrameworkCallbackResultContinue時,架構繼續執行,給分享組件事件(如果有,並且shouldAutoactivateShareKit返回YES)。並且當整個應用沒被載入時,調用BootLoader
* 當返回DTFrameworkCallbackResultReturn時,架構中止之後的邏輯,目前無其它邏輯。
*/
- (DTFrameworkCallbackResult)applicationDidBecomeActive:(UIApplication *)application;
/**
* 架構率先回調該方法。
* 當返回DTFrameworkCallbackResultContinue時,架構繼續執行,目前無其它邏輯。
* 當返回DTFrameworkCallbackResultReturn時,架構中止之後的邏輯,目前無其它邏輯。
*/
- (DTFrameworkCallbackResult)applicationWillTerminate:(UIApplication *)application;
/**
* 架構率先回調該方法。
* 當返回DTFrameworkCallbackResultContinue時,架構繼續執行,目前無其它邏輯。
* 當返回DTFrameworkCallbackResultReturn時,架構中止之後的邏輯,目前無其它邏輯。
*/
- (DTFrameworkCallbackResult)applicationDidReceiveMemoryWarning:(UIApplication *)application;
/**
* 架構率先回調該方法,接入應用可以先行處理Watch的訊息。
* 當返回DTFrameworkCallbackResultContinue時,架構會把Watch訊息通過UIApplicationWatchKitExtensionRequestNotifications廣播給全域監聽者。
* 當返回DTFrameworkCallbackResultReturn時,表示接入應用已經完全處理完通知訊息,架構中止執行之後的邏輯。
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void(^)(NSDictionary *replyInfo))reply;
/**
* 架構率先回調該方法,接入應用可以先行處理訊息。
* 當返回DTFrameworkCallbackResultContinue時,架構會把訊息通過UIApplicationUserActivityNotifications廣播給全域監聽者,並最後給系統返回NO。
* 當返回DTFrameworkCallbackResultReturnYES或DTFrameworkCallbackResultReturnNO時,架構直接給系統返回,不再執行接下來的邏輯。
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void(^)(NSArray *restorableObjects))restorationHandler;
/**
* 架構率先回調該方法,接入應用可以先行處理3D Touch快捷入口的訊息。
* 當返回DTFrameworkCallbackResultContinue時,架構會處理shortcutItem帶過來的URL,並最後調用completionHandler()返回是否已經處理。
* 當返回DTFrameworkCallbackResultReturn時,架構直接給系統返回,不再執行接下來的邏輯。
*/
- (DTFrameworkCallbackResult)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler;
/**
* Background Fetch 機制回調
* 必須在30s內回調completionHandler,否則進程將被terminate
* 若要啟用此機制,需要先配置Background Modes的fetch選項。其次在didFinishLaunching中調用下面的方法。更多資訊參考文檔。
* [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
* 預設實現為空白,需要接入方自己處理。
*/
- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
應用模組劃分
mPaaS 架構內定義了微應用和服務的概念來進行模組間的劃分。其中,以是否有 UI 介面作為標準,Framework 將不同的模組劃分為 微應用 和 服務,通過 架構上下文 進行微應用與服務的生命週期管理。
中文 | 英文 | 解釋 |
---|---|---|
微應用 | MicroApplication | 用戶端運行期帶有使用者介面的微應用 |
服務 | Service | 用戶端運行期提供的輕量級抽象服務 |
架構上下文 | Context | 用戶端微組件運行期上下文 |
本文主要介紹微應用、服務、架構內容相關的概念。有關具體的使用方法,查看 建立微應用。
微應用
在基於 mPaaS iOS 架構開發應用的過程中,一般會將帶有 UI 介面的獨立業務設定為一個微應用(如支付寶中的轉賬、手機儲值等),與其他的業務隔離開,實現各個微應用之間高度獨立,不相互依賴。
微應用也有自己的生命週期,整個過程如下:
微應用整個生命週期的回調方法,具體內容參考 DTMicroApplicationDelegate.h
檔案。
@required
/**
* 請求應用對象的代理返回根視圖控制器。
*
* @param application 應用對象。
*
* @return 應用的根視圖控制器。
*/
- (UIViewController *)rootControllerInApplication:(DTMicroApplication *)application;
@optional
/**
* 通知應用代理,應用對象已經對經被執行個體化。
*
* @param application 應用對象。
*/
- (void)applicationDidCreate:(DTMicroApplication *)application;
/**
* 通知應用代理,應用將要啟動。
*
* @param application 啟動的應用對象。
* @param options 應用運行參數。
*/
- (void)application:(DTMicroApplication *)application willStartLaunchingWithOptions:(NSDictionary *)options;
/**
* 通知應用代理,應用已啟動。
*
* @param application 啟動的應用對象。
*/
- (void)applicationDidFinishLaunching:(DTMicroApplication *)application;
/**
* 通知應用代理,應用即將暫停進入後台運行。
*
* @param application 啟動的應用對象。
*/
- (void)applicationWillPause:(DTMicroApplication *)application;
/**
* 通知應用代理,應用將被重新啟用。
*
* @param application 要啟用的應用對象。
*/
- (void)application:(DTMicroApplication *)application willResumeWithOptions:(NSDictionary *)options;
/**
* 通知應用代理,應用已經被啟用。
*
* @param application 要啟用的應用對象。
*/
- (void)applicationDidResume:(DTMicroApplication *)application;
/**
* 通知應用代理,應用已經被啟用。
*
* @param application 要啟用的應用對象,帶上參數的版本。
*/
- (void)application:(DTMicroApplication *)application didResumeWithOptions:(NSDictionary *)options;
/**
* 通知應用的代理,應用將要退出。
*
* @param application 應用對象。
*/
- (void)applicationWillTerminate:(DTMicroApplication *)application;
/**
* 通知應用的代理,應用將要退出。
*
* @param application 應用對象。
* @param animated 是否以動畫方式退出。
*/
- (void)applicationWillTerminate:(DTMicroApplication *)application animated:(BOOL)animated;
/**
* 詢問應用的代理,應用是否可以退出。
* 注意:只有特殊情況才返回 NO;如果預設是 YES,則可以退出。
*
* @param application 應用對象。
*
* @return 是否可以退出。
*/
- (BOOL)applicationShouldTerminate:(DTMicroApplication *)application;
服務
mPaaS iOS 架構將沒有 UI 介面的 Framework 稱為服務,其與微應用的區別如下:
微應用是獨立的商務程序,服務則用來提供泛型服務。
服務有狀態,一旦啟動後,其在整個用戶端的生命週期中一直存在,任何時候都可以被擷取;微應用在退出後即被銷毀。
服務管理相關的介面,具體內容參考 DTService.h
檔案。
@required
/**
* 啟動一個服務。
* 注意:
* 架構在完成初始化操作後,會調用該方法。
* 在一個服務裡面,要先調用該方法,之後才能去啟動應用。
*/
- (void)start;
@optional
/**
* 建立服務完成。
*/
- (void)didCreate;
/**
* 服務將要銷毀。
*/
- (void)willDestroy;
架構上下文(Context)
架構上下文(Context)是整個用戶端架構的控制中心,統一管理各個微應用和服務之間的互動與跳轉,主要負責:
提供啟動微應用的介面,可通過名字快速尋找、關閉、管理微應用的跳轉等。
提供啟動服務的介面,管理服務的註冊、發現和反註冊。
微應用管理
微應用管理相關介面,具體內容參考
DTContext.h
檔案。
/**
* 根據指定的名稱啟動一個應用。
*
* @param name 要啟動的應用程式名稱。
* @param params 啟動應用時,需要轉遞給另一個應用的參數。
* @param animated 指定啟動應用時,是否顯示動畫。
*
* @return 應用啟動成功返回 YES,否則返回 NO。
*/
- (BOOL)startApplication:(NSString *)name params:(NSDictionary *)params animated:(BOOL)animated;
/**
* 根據指定的名稱啟動一個應用。
*
* @param name 要啟動的應用程式名稱。
* @param params 啟動應用時,需要轉遞給另一個應用的參數。
* @param launchMode 指定 App 的啟動方式。
*
* @return 應用啟動成功返回 YES,否則返回 NO。
*/
- (BOOL)startApplication:(NSString *)name params:(NSDictionary *)params launchMode:(DTMicroApplicationLaunchMode)launchMode;
/**
* 尋找一下指定的應用。
*
* @param name 要尋找的應用程式名稱。
*
* @return 如果指定的應用已在應用棧中,則返回對應的應用對象。否則返回 nil。
*/
- (DTMicroApplication *)findApplicationByName:(NSString *)name;
/**
* 返回當前在棧頂的應用,即對使用者可見的應用。
*
* @return 當前可見的應用。
*/
- (DTMicroApplication *)currentApplication;
微應用啟動過程:
服務管理
服務管理相關介面,具體內容參考
DTContext.h
檔案。
/**
* 根據指定的名稱尋找服務。
*
* @param name 服務名
*
* @return 如果找到指定名稱的服務,則返回一個服務物件,否則返回空。
*/
- (id)findServiceByName:(NSString *)name;
/**
* 註冊一個服務。
*
* @param name 服務名
*/
- (BOOL)registerService:(id)service forName:(NSString *)name;
/**
* 反註冊一個已存在的服務。
*
* @param name 服務名。
*/
- (void)unregisterServiceForName:(NSString *)name;
服務啟動過程:
架構上下文管理微應用與服務的 UML 類圖如下: