自定義URL Schemesphp
一、引言數組
URL Schemes 應用在 iOS 上已經好久了。對於使用者來講,在沙盒機制下的 iOS 中,若是想作到必定程度上的自動化就不可避免地要用到 URL Schemes。但由於 URL Schemes 的使用方式不像傳統 iOS 使用者接觸到的圖形界面那樣能夠直觀地點來點去,形成了對它有興趣的人(尤爲是對英文有恐懼的人)必定程度上理解的困難。瀏覽器
二、簡介蘋果的沙盒機制安全
蘋果選擇沙盒來保障用戶的隱私和安全,但沙盒也阻礙了應用間合理的信息共享,因而有了 URL Schemes 這個解決辦法。微信
通常來講,咱們使用的智能設備上有許多咱們的我的信息。好比:聯繫方式、銀行卡/信用卡信息、支付寶/Paypal/各大商城的帳戶密碼、照片甚至行程與位置信息等。app
若是說,你設備上的每個應用,不論是官方的仍是你從任何商城安裝的應用均可以隨意地獲取這些信息,那麼你輕則收到騷擾信息和郵件、重則後果不堪設想。如何讓這些信息不被其它應用隨意使用,或者說,如何讓這些信息僅在設備全部者本人知情並容許的狀況下被使用,是全部智能設備與操做系統所要在意的核心安全問題。ide
在 iOS 這個操做系統中,針對這個問題,蘋果使用了名爲「沙盒」的機制:應用只能訪問它聲明可能訪問的資源。一切提交到 App Store 的應用都必須遵照這個機制。工具
在安全方面沙盒是個很好的解決辦法,可是有些矯枉過正。敏感的我的信息咱們不肯意透露,卻不表明全部的信息咱們都不想與其它應用共享。post
好比說咱們要一次性地(沒錯,只按一次)把多個事件放到日曆中,這些事件包含日期時間以及持續時間等信息,若是 App 之間信息不能溝通,就沒法作到這點。(在下文中的 x-callback-URL 的部分會詳述整個過程)url
相似於一次性添加多個日曆事件這樣的,咱們在使用智能設備的過程當中會遇到不少沒必要要的重複的步驟。大多數人對這些重複的步驟是不自覺的,就像當本身電腦裏有一批文件須要批量重命名的時候,他們機械地重複着重命名的過程。可是當咱們掌握了這些設備運行的模式,或者有了一些工具,咱們就能將這些重複的步驟所有節省下來。在 iOS 上,咱們能夠利用的工具就是 URL Schemes。
三、URL Schemes 是什麼
Custom URL scheme 的好處就是,你能夠在其它程序中經過這個url打開應用程序。如A應用程序註冊了一個url scheme:myApp, 那麼就在mobile瀏覽器中就能夠經過<href=’myApp://’>打開你的應用程序A。
對比網頁url就比較好理解url scheme。給出一個url 「http://bxu2359670321.my3w.com/view/login.php」,它的格式:protocol :// hostname[:port] / path / [;parameters][?query]#fragment。 所以這個url的protocol就是http。對比URL Scheme,給出例子「weixin://dl/moments「,前面的weixin:就表明微信的scheme。你能夠徹底按照理解一個網頁的 URL ——也就是它的網址——的方式來理解一個 iOS 應用的 URL。即Scheme是**://**以前的那段字符
###注意###
一、全部的網頁都有url;但未必全部的應用都有本身的 URL Schemes,更不是每一個應用的每一個功能都有相應的 URL Schemes
二、一個網址只對應一個網頁,但並不是每一個 URL Schemes 都只對應一款應用。這點是由於蘋果沒有對 URL Schemes 有不容許重複的硬性要求
三、通常網頁的 URL 比較好預測,而 iOS 上的 URL Schemes 由於沒有統一標準,因此很是難猜,經過猜來獲取 iOS 應用的 URL Schemes 是不現實的。(我推薦將Bundle identifier反轉)
###上乾貨###
一、註冊自定義 URL Scheme
1)註冊自定義 URL Scheme 的第一步是建立 URL Scheme — 在 Xcode Project Navigator 中找到並點擊工程 info.plist 文件。當該文件顯示在右邊窗口,在列表上點擊鼠標右鍵,選擇 Add Row:
2)點擊左邊剪頭打開列表,能夠看到 Item 0,一個字典實體。展開 Item 0,能夠看到 URL Identifier,一個字符串對象。該字符串是你自定義的 URL scheme 的名字。建議採用反轉Bundle idenmtifier的方法保證該名字的惟一性
3)點擊 Item 0 新增一行,從下拉列表中選擇 URL Schemes,敲擊鍵盤迴車鍵完成插入。(注意 URL Schemes 是一個數組,容許應用定義多個 URL schemes。)展開該數據並點擊 Item 0。你將在這裏定義自定義 URL scheme 的名字。只須要名字,不要在後面追加 ://
二、拿瀏覽器坐簡單驗證
在地址欄中熟入自定的url scheme。此時必須保證該瀏覽器所在設備上已經安裝了具備自定義url scheme的App。
三、新建Xcode工程,作個App試試看,這裏我就放一個Button,點擊打開url 代碼。
- (IBAction)open:(id)sender { NSString *url = @"zhunaer://?name=lbp&age=22"; if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:url]]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]]; }else{ NSLog(@"打不開"); } }
結果打不開,爲何? 由於在新建App的plist中沒加query schemes
<key>LSApplicationQueriesSchemes</key> <array> <string>zhunaer</string> </array>
四、若是須要在2個App之間傳值,怎麼辦?能夠用URL Scheme解決。
在被打開的App的Appdelegate.m中實現-(BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nonnull id)annotation;
-(BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nonnull id)annotation{ NSLog(@"calling application bundle id: %@",sourceApplication); NSLog(@"url shceme:%@",[url scheme]); NSLog(@"參數:%@",[url query]); if ([sourceApplication isEqualToString:@"com.geek.test1"]) { return YES; } return NO; }
在須要打開第三方App的點擊事件處的url處後面加上參數,相似NSString *url = @"zhunaer://?name=lbp&age=22";
注意:在URL Scheme後加?而後跟網頁的url的參數同樣寫法。
五、如何判斷是指定App打開,或者某些App不讓打開咱們的App? 作了實驗。
A:在須要打開第三方App的工程中將Bundle identifier改成「com.geek.test2」,其他不變
B:在被打開的App的AppDelegate.m中
-(BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(nonnull id)annotation{ NSLog(@"calling application bundle id: %@",sourceApplication); NSLog(@"url shceme:%@",[url scheme]); NSLog(@"參數:%@",[url query]); if ([sourceApplication isEqualToString:@"com.geek.test1"]) { return YES; } return NO; }
###實驗結果###
依舊能夠打開App,即便斷點走入Return NO
結論:若是你想阻止其它應用調用你的應用,建立一個不同凡響的 URL scheme。儘管這不能保證你的應用不會被調用,但至少大大下降了這種可能性。