按照 SDK 是否有界面來進行分類,我們開發的 SDK 無外乎就兩類:
- 帶有 UI 界面的 SDK,我們開發的大部分 SDK 都是這一類
- 不帶有 UI 界面的 SDK,比如 token 計算的 SDK
從接口設計角度,前者比較復雜,本文介紹如何設計 外部APP 頁面到 SDK 內部頁面的跳轉。
1. 跳轉分析
iOS 頁面呈現,最常用的方式有兩類:
- present ViewController
- navigation controller push ViewController
- 使用 UIWindow
設計的時候有以下幾個點需要注意:
- 外部 APP 調用頁面類型未知,調用 SDK 的有可能是普通的 ViewController,也有可能是 navigation controller ,還有可能是一個 tabbar ViewController,...
- 不能污染外部的頁面,退出 SDK 的時候要還原全局設置,比如 status bar 的隱藏和顯示狀態,status bar 的 UI 風格是淺色還是深色,頁面是否常亮,...
2. 跳轉的最終方案
在我們的 SDK 中,進入 SDK 頁面有兩種主流方案:
- 使用 UIWindow 呈現 SDK
- 使用 present 方式,SDK 內部頁面用 navigation controller 管理
我們諸多 SDK 中,兩種方式都有用到,本文講解后者。
由于 SDK 中涉及到頁面 push,最終選擇的方案是在 APP 的調用頁面,present navigation controller,將 SDK 的首頁設置為 navigation controller 的 root ViewController。
3. 跳轉相關細節
SDK 鑒權
先對外部傳入的參數進行校驗,權限查詢,這一步驟通過之后,才能進入下一步驟。
獲取 APP 調用 SDK 的 ViewController
基本思路是,獲取當前 APP keyWindow 的 rootViewController,然后分類逐層找到最上層的 ViewController。
#pragma mark - private method
// 獲取應用當前界面,調用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;
}
}
跳轉
通過上面步驟,獲取到 rootViewController ,然后在 rootViewController 基礎上進行跳轉。
WBNavigationController *nav = [[WBNavigationController alloc] initWithRootViewController:[self getTargetViewController]];
[rootViewController presentViewController:nav animated:NO completion:nil];
其中,WBNavigationController 繼承自 UINavigationController;
SDK 中包含多個業務,不同業務進入的頁面不一樣,getTargetViewController
方法獲取當次業務對應的目標頁面。