什么是URL Scheme
簡(jiǎn)單的說,由于蘋果選擇使用沙盒機(jī)制來保障用戶的隱私和安全,APP只能訪問自己沙盒數(shù)據(jù),但同時(shí)也阻礙了應(yīng)用間合理的信息共享。因此蘋果提供了一個(gè)可以在APP之間跳轉(zhuǎn)的方法:URL Scheme。如果你的APP需要其他APP訪問某些功能或者數(shù)據(jù),那么你需要在你的APP定義一個(gè)相應(yīng)的URL Scheme。當(dāng)別的APP使用URL Scheme進(jìn)行訪問時(shí),系統(tǒng)會(huì)根據(jù)URL Scheme進(jìn)行匹配,從而來拉起對(duì)應(yīng)的APP。
如何理解URL Scheme
如果想要更清晰的認(rèn)識(shí)URL Scheme電話,我們需要了解下面幾個(gè)概念:
URL(Uniform Resource Locator:統(tǒng)一資源定位器):也就是我們所屬于的"網(wǎng)址",通過它我們可以訪問到我們想要的服務(wù)和資源,并且URL也可以傳遞相應(yīng)的參數(shù),也就是我們常說的GET請(qǐng)求;
URL地址格式排列為:scheme://host:port/path,舉個(gè)栗子:http://www.lxweimin.com/u/b09c13696e1c就是個(gè)典型的URL,而這個(gè)網(wǎng)址對(duì)應(yīng)的Scheme就是https,標(biāo)識(shí)的是一個(gè)URL中的一個(gè)位置——最初始的位置,也可以理解為一種協(xié)議頭。而我們自定義的URL Scheme可以理解為一種自定義的協(xié)議。
根據(jù)我們上面對(duì)URL Scheme的理解,我們可以很輕易地理解,在以本地應(yīng)用為主的iOS上,我們可以像定位一個(gè)網(wǎng)頁一樣,用一種特殊的URL來定位一個(gè)應(yīng)用甚至應(yīng)用里某個(gè)具體的功能。而定位這個(gè)應(yīng)用的標(biāo)識(shí),也就是Scheme。比如微信的Scheme是weixin,打開微信掃一掃功能的URL Scheme則是weixin://dl/scan。
這樣一對(duì)比就容易很明白的理解出了URL Scheme的真正含義,它是為了在iOS系統(tǒng)中定位對(duì)應(yīng)的App然后執(zhí)行對(duì)應(yīng)的操作,復(fù)雜的URL Scheme還可以傳遞參數(shù)。
URL Scheme的應(yīng)用場(chǎng)景
使用iOS系統(tǒng)預(yù)設(shè)的URL Scheme調(diào)用系統(tǒng)APP:iOS系統(tǒng)內(nèi)置的App,如mail,電話等等,都有相應(yīng)的URL Scheme供其他的APP調(diào)用。比如下面的代碼就是使用系統(tǒng)的電話APP給18888888888打電話。
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel://18888888888"]];以下是一些URL Scheme合集:
使用URL Scheme讓別的應(yīng)用打開當(dāng)前APP,自己的APP寫好一下可以讓其他APP來使用的功能,或者當(dāng)前APP使用其他APP提供的服務(wù)。比如支付寶,當(dāng)APP使用支付寶支付是,就可以使用支付寶定義好的Scheme來訪問支付寶支付功能。因?yàn)閁RL可以攜帶一些參數(shù)因此我們也可以進(jìn)行一些數(shù)據(jù)的共享。
web頁面通過URL Scheme來使用APP的一些功能。web可以通過window.location.href跳轉(zhuǎn)方式跳轉(zhuǎn)對(duì)應(yīng)的URL Scheme從而來使用APP中一些功能。相對(duì)比較常用的URL Scheme的應(yīng)用場(chǎng)景。
進(jìn)行App內(nèi)頁面跳轉(zhuǎn)。在傳統(tǒng)意義上的頁面跳轉(zhuǎn),無非也就是以下幾種方式:
Storyboard的segues方式跳轉(zhuǎn)
直接跳轉(zhuǎn)present,dismiss跳轉(zhuǎn)
UINavigationController的push,pop跳轉(zhuǎn)
這些方式其實(shí)都有一個(gè)缺點(diǎn),那就是跳轉(zhuǎn)很不靈活,如果想讓一個(gè)模塊根據(jù)需求動(dòng)態(tài)的跳轉(zhuǎn)不同頁面,傳遞不同的參數(shù),那么就必須書寫很多復(fù)雜的邏輯幾句一些情況也選擇要跳轉(zhuǎn)的邏輯。
或許你說我可以通過控制器的名字來創(chuàng)建對(duì)應(yīng)的控制器進(jìn)行動(dòng)態(tài)的跳轉(zhuǎn),但事實(shí)上這樣的方式如果僅僅進(jìn)行跳轉(zhuǎn)還是能滿足需求的,但是在傳遞參數(shù)方面就是閑的力不從心。
所以說了那么多,有一種跳轉(zhuǎn)方式可以既滿足跳轉(zhuǎn)的動(dòng)態(tài)需求,也可以靈活的傳遞參數(shù)。這種方式就是使用URL Scheme進(jìn)行動(dòng)態(tài)跳轉(zhuǎn)。這也是我非常推薦的一種使用方式。并且在一些組件化開發(fā)的嘗試中,這種跳轉(zhuǎn)方式也帶來了很多便利。
使用URL Scheme跳轉(zhuǎn)的好處
URL Scheme跳轉(zhuǎn)方式比較靈活,只需要本地進(jìn)行簡(jiǎn)單邏輯處理,使用openURL來打開對(duì)應(yīng)的控制器,而這個(gè)你想要打開的URL Scheme是可以動(dòng)態(tài)的從服務(wù)器動(dòng)態(tài)獲取的。那么這樣就很簡(jiǎn)單的實(shí)現(xiàn)了動(dòng)態(tài)跳轉(zhuǎn)。
URL Scheme傳遞參數(shù)的方式也與URL一致,只需要簡(jiǎn)單的在URL里附加上對(duì)應(yīng)的參數(shù)即可。
這種頁面跳轉(zhuǎn)是無差別的,通過URL Scheme跳轉(zhuǎn)可以無縫的在H5頁面和原生頁面之間跳轉(zhuǎn)傳值,而無需做更多的邏輯判斷。
使用URL Scheme跳轉(zhuǎn)的缺點(diǎn)
寫在info.plist文件中的Scheme可能會(huì)被一些反編譯手段獲取到。
URL Scheme可能會(huì)被劫持調(diào)來安全隱患,比如支付寶的URL Scheme劫持漏洞。
當(dāng)然這是避免的,以下引自烏云:
蘋果可以限制 iOS 應(yīng)用不能注冊(cè)別的應(yīng)用的 Bundle ID 作為 URL Scheme。這樣的話,使用自己的 Bundle ID 作為 URL Scheme 的接收器就會(huì)變的安全很多。
第三方應(yīng)用可以通過①給自己發(fā)送 URL Scheme 請(qǐng)求來證明沒有被劫持,如果沒有收到自己的 URL Scheme,就可以及時(shí)給用戶發(fā)送提醒;②利用 MobileCoreServices 服務(wù)中的 applicationsAvailableForHandlingURLScheme() 來查看所有注冊(cè)了該 URL Schemes 的應(yīng)用和處理順序,從而檢測(cè)自己、或者別人的 URL Scheme 是否被劫持。
注冊(cè)自定義URL Scheme
注冊(cè)自定義URL Scheme有兩種方式
在工程中的info.plist文件中添加對(duì)應(yīng)的key值
tagets -> info -> URL Types 中添加
這兩種注冊(cè)方式本質(zhì)上其實(shí)是一樣的只是位置不同。
URL Scheme相關(guān)驗(yàn)證
從其他應(yīng)用或Safari中使用URL Scheme拉起APP
我們需要在APPdelegate中實(shí)現(xiàn)相應(yīng)的代理方法:
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來驗(yàn)證:
- (BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary *)options {NSLog(@"%s",__func__);NSLog(@"options: %@", options);NSLog(@"URL scheme:%@", [url scheme]);NSLog(@"URL query: %@", [url query]);// 提示并展示queryUIAlertView*alertView = [[UIAlertViewalloc] initWithTitle:@"打開URL Scheme成功"message:[url query]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delegate:nilcancelButtonTitle:@"確定"otherButtonTitles:nil];? ? [alertView show];returnYES;}
在當(dāng)前應(yīng)用中使用URL Scheme
在應(yīng)用中調(diào)用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("");
還有一個(gè)方法可以判斷對(duì)應(yīng)URL Scheme是否存在一般和上述方法一起使用:
- (BOOL)canOpenURL:(NSURL *)url NS_AVAILABLE_IOS(3_0);
下面來驗(yàn)證一下:
- (void)btnClick:(UIButton *)sender {? ? [[UIApplication sharedApplication]openURL:[NSURLURLWithString:@"schemeDemo://"]options:@{}completionHandler:^(BOOL success) {? ? ? ? NSLog(@"完成");? ? }];}