按照 SDK 是否有界面來進(jìn)行分類,我們開發(fā)的 SDK 無外乎就兩類:
- 帶有 UI 界面的 SDK,我們開發(fā)的大部分 SDK 都是這一類
- 不帶有 UI 界面的 SDK,比如 token 計算的 SDK
從接口設(shè)計角度,前者比較復(fù)雜,本文介紹如何設(shè)計 外部APP 頁面到 SDK 內(nèi)部頁面的跳轉(zhuǎn)。
1. 跳轉(zhuǎn)分析
iOS 頁面呈現(xiàn),最常用的方式有兩類:
- present ViewController
- navigation controller push ViewController
- 使用 UIWindow
設(shè)計的時候有以下幾個點需要注意:
- 外部 APP 調(diào)用頁面類型未知,調(diào)用 SDK 的有可能是普通的 ViewController,也有可能是 navigation controller ,還有可能是一個 tabbar ViewController,...
- 不能污染外部的頁面,退出 SDK 的時候要還原全局設(shè)置,比如 status bar 的隱藏和顯示狀態(tài),status bar 的 UI 風(fēng)格是淺色還是深色,頁面是否常亮,...
2. 跳轉(zhuǎn)的最終方案
在我們的 SDK 中,進(jìn)入 SDK 頁面有兩種主流方案:
- 使用 UIWindow 呈現(xiàn) SDK
- 使用 present 方式,SDK 內(nèi)部頁面用 navigation controller 管理
我們諸多 SDK 中,兩種方式都有用到,本文講解后者。
由于 SDK 中涉及到頁面 push,最終選擇的方案是在 APP 的調(diào)用頁面,present navigation controller,將 SDK 的首頁設(shè)置為 navigation controller 的 root ViewController。
3. 跳轉(zhuǎn)相關(guān)細(xì)節(jié)
SDK 鑒權(quán)
先對外部傳入的參數(shù)進(jìn)行校驗,權(quán)限查詢,這一步驟通過之后,才能進(jìn)入下一步驟。
獲取 APP 調(diào)用 SDK 的 ViewController
基本思路是,獲取當(dāng)前 APP keyWindow 的 rootViewController,然后分類逐層找到最上層的 ViewController。
#pragma mark - private method
// 獲取應(yīng)用當(dāng)前界面,調(diào)用SDK的界面
- (UIViewController*)topViewController {
return [self topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController];
}
- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
if ([rootViewController isKindOfClass:[UITabBarController class]]) {
NSLog(@"root:UITabBarController");
UITabBarController* tabBarController = (UITabBarController*)rootViewController;
return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
} else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
NSLog(@"root:UINavigationController");
UINavigationController* navigationController = (UINavigationController*)rootViewController;
return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
} else if (rootViewController.presentedViewController) {
NSLog(@"root:rootViewController.presentedViewController");
UIViewController* presentedViewController = rootViewController.presentedViewController;
return [self topViewControllerWithRootViewController:presentedViewController];
} else {
NSLog(@"root:rootViewController");
return rootViewController;
}
}
跳轉(zhuǎn)
通過上面步驟,獲取到 rootViewController ,然后在 rootViewController 基礎(chǔ)上進(jìn)行跳轉(zhuǎn)。
WBNavigationController *nav = [[WBNavigationController alloc] initWithRootViewController:[self getTargetViewController]];
[rootViewController presentViewController:nav animated:NO completion:nil];
其中,WBNavigationController 繼承自 UINavigationController;
SDK 中包含多個業(yè)務(wù),不同業(yè)務(wù)進(jìn)入的頁面不一樣,getTargetViewController 方法獲取當(dāng)次業(yè)務(wù)對應(yīng)的目標(biāo)頁面。