iOS 喚起APP之URL Scheme

什麼是URL Scheme

簡單的說,因爲蘋果選擇使用沙盒機制來保障用戶的隱私和安全,APP只能訪問本身沙盒數據,但同時也阻礙了應用間合理的信息共享。所以蘋果提供了一個能夠在APP之間跳轉的方法:URL Scheme。若是你的APP須要其餘APP訪問某些功能或者數據,那麼你須要在你的APP定義一個相應的URL Scheme。當別的APP使用URL Scheme進行訪問時,系統會根據URL Scheme進行匹配,從而來拉起對應的APP。html

如何理解URL Scheme

若是想要更清晰的認識URL Scheme電話,咱們須要瞭解下面幾個概念:web

  1. URL(Uniform Resource Locator:統一資源定位器):也就是咱們所屬於的"網址",經過它咱們能夠訪問到咱們想要的服務和資源,而且URL也能夠傳遞相應的參數,也就是咱們常說的GET請求;
  2. URL地址格式排列爲:scheme://host:port/path,舉個栗子:https://www.jianshu.com/u/b09c13696e1c就是個典型的URL,而這個網址對應的Scheme就是https,標識的是一個URL中的一個位置——最初始的位置,也能夠理解爲一種協議頭。而咱們自定義的URL Scheme能夠理解爲一種自定義的協議。
  3. 根據咱們上面對URL Scheme的理解,咱們能夠很輕易地理解,在以本地應用爲主的iOS上,咱們能夠像定位一個網頁同樣,用一種特殊的URL來定位一個應用甚至應用裏某個具體的功能。而定位這個應用的標識,也就是Scheme。好比微信的Schemeweixin,打開微信掃一掃功能的URL Scheme則是weixin://dl/scan

這樣一對比就容易很明白的理解出了URL Scheme的真正含義,它是爲了在iOS系統中定位對應的App而後執行對應的操做,複雜的URL Scheme還能夠傳遞參數。安全

URL Scheme的應用場景

  1. 使用iOS系統預設的URL Scheme調用系統APP:iOS系統內置的App,如mail,電話等等,都有相應的URL Scheme供其餘的APP調用。好比下面的代碼就是使用系統的電話APP給18888888888打電話。
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://18888888888"]];如下是一些URL Scheme合集:
  1. 使用URL Scheme讓別的應用打開當前APP,本身的APP寫好一下可讓其餘APP來使用的功能,或者當前APP使用其餘APP提供的服務。好比支付寶,當APP使用支付寶支付是,就可使用支付寶定義好的Scheme來訪問支付寶支付功能。由於URL能夠攜帶一些參數所以咱們也能夠進行一些數據的共享。
  2. web頁面經過URL Scheme來使用APP的一些功能。web能夠經過window.location.href跳轉方式跳轉對應的URL Scheme從而來使用APP中一些功能。相對比較經常使用的URL Scheme的應用場景。
  3. 進行App內頁面跳轉。在傳統意義上的頁面跳轉,無非也就是如下幾種方式:
    • Storyboard的segues方式跳轉
    • 直接跳轉present,dismiss跳轉
    • UINavigationController的push,pop跳轉
    這些方式其實都有一個缺點,那就是跳轉很不靈活,若是想讓一個模塊根據需求動態的跳轉不一樣頁面,傳遞不一樣的參數,那麼就必須書寫不少複雜的邏輯幾句一些狀況也選擇要跳轉的邏輯。
    或許你說我能夠經過控制器的名字來建立對應的控制器進行動態的跳轉,但事實上這樣的方式若是僅僅進行跳轉仍是能知足需求的,可是在傳遞參數方面就是閒的力不從心。

因此說了那麼多,有一種跳轉方式能夠既知足跳轉的動態需求,也能夠靈活的傳遞參數。這種方式就是使用URL Scheme進行動態跳轉。這也是我很是推薦的一種使用方式。而且在一些組件化開發的嘗試中,這種跳轉方式也帶來了不少便利。服務器

使用URL Scheme跳轉的好處

  1. URL Scheme跳轉方式比較靈活,只須要本地進行簡單邏輯處理,使用openURL來打開對應的控制器,而這個你想要打開的URL Scheme是能夠動態的從服務器動態獲取的。那麼這樣就很簡單的實現了動態跳轉。
  2. URL Scheme傳遞參數的方式也與URL一致,只須要簡單的在URL裏附加上對應的參數便可。
  3. 這種頁面跳轉是無差異的,經過URL Scheme跳轉能夠無縫的在H5頁面和原生頁面之間跳轉傳值,而無需作更多的邏輯判斷。

使用URL Scheme跳轉的缺點

  1. 寫在info.plist文件中的Scheme可能會被一些反編譯手段獲取到。
  2. URL Scheme可能會被劫持調來安全隱患,好比支付寶的URL Scheme劫持漏洞。
    固然這是避免的,如下引自烏雲:

蘋果能夠限制 iOS 應用不能註冊別的應用的 Bundle ID 做爲 URL Scheme。這樣的話,使用本身的 Bundle ID 做爲 URL Scheme 的接收器就會變的安全不少。微信

第三方應用能夠經過①給本身發送 URL Scheme 請求來證實沒有被劫持,若是沒有收到本身的 URL Scheme,就能夠及時給用戶發送提醒;②利用 MobileCoreServices 服務中的 applicationsAvailableForHandlingURLScheme() 來查看全部註冊了該 URL Schemes 的應用和處理順序,從而檢測本身、或者別人的 URL Scheme 是否被劫持。app

註冊自定義URL Scheme

註冊自定義URL Scheme有兩種方式組件化

  1. 在工程中的info.plist文件中添加對應的key值


    url

  2. tagets -> info -> URL Types 中添加

    代理

這兩種註冊方式本質上實際上是同樣的只是位置不一樣。code

URL Scheme相關驗證

從其餘應用或Safari中使用URL Scheme拉起APP

咱們須要在APPdelegate中實現相應的代理方法:

iOS 9.0如下
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
iOS 9.0以上
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;

下面咱們經過Safari來驗證:


- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
    NSLog(@"%s",__func__);
    NSLog(@"options: %@", options);
    NSLog(@"URL scheme:%@", [url scheme]);
    NSLog(@"URL query: %@", [url query]);
    
    // 提示並展現query
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"打開URL Scheme成功"
                                                        message:[url query]
                                                       delegate:nil
                                              cancelButtonTitle:@"肯定"
                                              otherButtonTitles:nil];
    [alertView show];
    
    return YES;
}

在當前應用中使用URL Scheme

在應用中調用URL Scheme須要是如下方法:

iOS10.0如下使用該方法:
- (BOOL)openURL:(NSURL*)url NS_DEPRECATED_IOS(2_0, 10_0, "Please use openURL:options:completionHandler: instead") NS_EXTENSION_UNAVAILABLE_IOS("");
iOS10.0以上使用該方法:
- (void)openURL:(NSURL*)url options:(NSDictionary<UIApplicationOpenExternalURLOptionsKey, id> *)options completionHandler:(void (^ __nullable)(BOOL success))completion NS_AVAILABLE_IOS(10_0) NS_EXTENSION_UNAVAILABLE_IOS("");
還有一個方法能夠判斷對應URL Scheme是否存在通常和上述方法一塊兒使用:
- (BOOL)canOpenURL:(NSURL *)url NS_AVAILABLE_IOS(3_0);

下面來驗證一下:

- (void)btnClick:(UIButton *)sender {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"schemeDemo://"] options:@{} completionHandler:^(BOOL success) {
        NSLog(@"完成");
    }];
}

相關文章
相關標籤/搜索