mPaaS 框架介绍

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 界面的独立业务设置为一个微应用(如支付宝中的转账、手机充值等),与其他的业务隔离开,实现各个微应用之间高度独立,不相互依赖。

微应用也有自己的生命周期,整个过程如下:

applicationSchedule

微应用整个生命周期的回调方法,具体内容参考 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;
  • 微应用启动过程:

app-launcher

服务管理

  • 服务管理相关接口,具体内容参考 DTContext.h 文件。

/**
 * 根据指定的名称查找服务。
 *
 * @param name 服务名
 *
 * @return 如果找到指定名称的服务,则返回一个服务对象,否则返回空。
 */
- (id)findServiceByName:(NSString *)name;

/**
 * 注册一个服务。
 *
 * @param name 服务名
 */
- (BOOL)registerService:(id)service forName:(NSString *)name;

/**
 * 反注册一个已存在的服务。
 *
 * @param name 服务名。
 */
- (void)unregisterServiceForName:(NSString *)name;
  • 服务启动过程:

    service-Launcher

框架上下文管理微应用与服务的 UML 类图如下:

uml