什么是URL Scheme
簡單的說,由於蘋果選擇使用沙盒機制來保障用戶的隱私和安全,APP只能訪問自己沙盒數據,但同時也阻礙了應用間合理的信息共享。因此蘋果提供了一個可以在APP之間跳轉的方法:URL Scheme
。如果你的APP需要其他APP訪問某些功能或者數據,那么你需要在你的APP定義一個相應的URL Scheme
。當別的APP使用URL Scheme
進行訪問時,系統會根據URL Scheme
進行匹配,從而來拉起對應的APP。
如何理解URL Scheme
如果想要更清晰的認識URL Scheme
電話,我們需要了解下面幾個概念:
URL
(Uniform Resource Locator:統一資源定位器):也就是我們所屬於的"網址",通過它我們可以訪問到我們想要的服務和資源,並且URL
也可以傳遞相應的參數,也就是我們常說的GET
請求;URL
地址格式排列為:scheme://host:port/path
,舉個栗子:https://www.jianshu.com/u/b09c13696e1c就是個典型的URL
,而這個網址對應的Scheme
就是https
,標識的是一個URL
中的一個位置——最初始的位置,也可以理解為一種協議頭。而我們自定義的URL Scheme
可以理解為一種自定義的協議。- 根據我們上面對
URL Scheme
的理解,我們可以很輕易地理解,在以本地應用為主的iOS
上,我們可以像定位一個網頁一樣,用一種特殊的URL
來定位一個應用甚至應用里某個具體的功能。而定位這個應用的標識,也就是Scheme
。比如微信的Scheme
是weixin
,打開微信掃一掃功能的URL Scheme
則是weixin://dl/scan
。
這樣一對比就容易很明白的理解出了URL Scheme的真正含義,它是為了在iOS系統中定位對應的App然后執行對應的操作,復雜的URL Scheme還可以傳遞參數。
URL Scheme
的應用場景
- 使用iOS系統預設的
URL Scheme
調用系統APP:iOS系統內置的App,如mail,電話等等,都有相應的URL Scheme
供其他的APP調用。比如下面的代碼就是使用系統的電話APP給18888888888打電話。
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://18888888888"]];以下是一些URL Scheme
合集:
- [常用的
URL Scheme
合集](常用的URL Scheme.md)
-
使用
URL Scheme
讓別的應用打開當前APP,自己的APP寫好一下可以讓其他APP來使用的功能,或者當前APP使用其他APP提供的服務。比如支付寶,當APP使用支付寶支付是,就可以使用支付寶定義好的Scheme來訪問支付寶支付功能。因為URL
可以攜帶一些參數因此我們也可以進行一些數據的共享。 -
web頁面通過
URL Scheme
來使用APP的一些功能。web可以通過window.location.href
跳轉方式跳轉對應的URL Scheme
從而來使用APP中一些功能。相對比較常用的URL Scheme
的應用場景。 -
進行App內頁面跳轉。在傳統意義上的頁面跳轉,無非也就是以下幾種方式:
- Storyboard的segues方式跳轉
- 直接跳轉present,dismiss跳轉
- UINavigationController的push,pop跳轉
這些方式其實都有一個缺點,那就是跳轉很不靈活,如果想讓一個模塊根據需求動態的跳轉不同頁面,傳遞不同的參數,那么就必須書寫很多復雜的邏輯幾句一些情況也選擇要跳轉的邏輯。
或許你說我可以通過控制器的名字來創建對應的控制器進行動態的跳轉,但事實上這樣的方式如果僅僅進行跳轉還是能滿足需求的,但是在傳遞參數方面就是閑的力不從心。
所以說了那么多,有一種跳轉方式可以既滿足跳轉的動態需求,也可以靈活的傳遞參數。這種方式就是使用URL Scheme進行動態跳轉。這也是我非常推薦的一種使用方式。並且在一些組件化開發的嘗試中,這種跳轉方式也帶來了很多便利。
使用URL Scheme跳轉的好處
URL Scheme
跳轉方式比較靈活,只需要本地進行簡單邏輯處理,使用openURL
來打開對應的控制器,而這個你想要打開的URL Scheme是可以動態的從服務器動態獲取的。那么這樣就很簡單的實現了動態跳轉。- URL Scheme傳遞參數的方式也與URL一致,只需要簡單的在URL里附加上對應的參數即可。
- 這種頁面跳轉是無差別的,通過URL Scheme跳轉可以無縫的在H5頁面和原生頁面之間跳轉傳值,而無需做更多的邏輯判斷。
使用URL Scheme跳轉的缺點
- 寫在info.plist文件中的Scheme可能會被一些反編譯手段獲取到。
- URL Scheme可能會被劫持調來安全隱患,比如支付寶的URL Scheme劫持漏洞。
當然這是避免的,以下引自烏雲:
蘋果可以限制 iOS 應用不能注冊別的應用的 Bundle ID 作為 URL Scheme。這樣的話,使用自己的 Bundle ID 作為 URL Scheme 的接收器就會變的安全很多。
第三方應用可以通過①給自己發送 URL Scheme 請求來證明沒有被劫持,如果沒有收到自己的 URL Scheme,就可以及時給用戶發送提醒;②利用 MobileCoreServices 服務中的 applicationsAvailableForHandlingURLScheme() 來查看所有注冊了該 URL Schemes 的應用和處理順序,從而檢測自己、或者別人的 URL Scheme 是否被劫持。
注冊自定義URL Scheme
注冊自定義URL Scheme有兩種方式
-
在工程中的info.plist文件中添加對應的key值
-
tagets -> info -> URL Types 中添加
這兩種注冊方式本質上其實是一樣的只是位置不同。
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(@"完成");
}];
}
- 常用的
URL Scheme
合集
文章若有不對地方,歡迎批評指正