日常咱們作iOS開發,會常常遇到打開其餘的APP的功能。本篇文章講的就是打開別人的APP的一些知識。咱們的目標是:ios
創建一個名爲MyApp的iOS工程。這個MyApp是「個人app」,用來打開另外一個APP的。
添加工程到咱們剛纔建立的OpenApp.xcworkspace。而且在工程的Main.storyboard添加一個button,待會兒咱們會用來寫方法。git
創建一個名爲WXApp的iOS工程。這個工程是咱們模擬的「微信APP」,是被人打開的那個APP。
爲了區分兩個應用,咱們在Main.storyboard上加一個label,「我是微信App」。github
好了,準備工做就這麼簡單。瀏覽器
想要打開別人的APP或者讓別人打開咱們的APP,那就須要經過URL Schemes了。微信
URL Schemes是蘋果給出的用來跳轉到系統應用或者跳轉到別人的應用的一種機制。同時還能夠在應用之間傳數據。app
經過對比網頁連接來理解 iOS 上的 URL Schemes,應該就容易多了。
URL Schemes 有兩個單詞:ui
- URL,咱們都很清楚,http://www.apple.com
就是個 URL,咱們也叫它連接或網址;- Schemes,表示的是一個 URL 中的一個位置——最初始的位置,即 ://
以前的那段字符。好比 http://www.apple.com
這個網址的 Schemes是 http。
根據咱們上面對 URL Schemes 的使用,咱們能夠很輕易地理解,在以本地應用爲主的 iOS 上,咱們能夠像定位一個網頁同樣,用一種特殊的 URL 來定位一個應用甚至應用裏某個具體的功能。而定位這個應用的,就應該是這個應用的 URL 的 Schemes 部分,也就是開頭兒那部分。
爲了能讓別的App(包括咱們剛纔建立的MyApp)可以打開WXApp,咱們須要爲WXApp添加一個URL Schemes。
步驟:選中WXApp工程->Info->URL Types->點擊「+」->在URL Schemes欄填上 weixin
url
備註:一個應用是能夠有多個URL Schemes的。你能夠再次點擊「+」來添加一個URL Schemesspa
咱們看看info.plist文件裏面是怎樣的。3d
而後咱們run一下WXApp。(注意一下你run的target是哪一個)
這樣,WXApp就向系統「註冊」了一個URL Schemes,其餘的應用能夠經過openurl:
方法來打開WXApp了。
如今咱們在MyApp裏面打開WXApp。方法很是簡單。
在ViewController裏面添加一個方法
- (IBAction)openWXApp:(UIButton *)sender { [self demo1]; } - (void)demo1 { //建立一個url,這個url就是WXApp的url,記得加上:// NSURL *url = [NSURL URLWithString:@"weixin://"]; //打開url [[UIApplication sharedApplication] openURL:url]; }
而後run一下MyApp
運行了以後點擊「打開微信」button,會彈出「MyApp」想要打開「WXApp」
提示框,點確認以後就能夠跳轉到WXApp了。
iOS9以後,在一個應用跳轉到了另外一個應用以後,左上角會有個返回到上一個應用的按鈕。這樣,咱們在MyApp裏面點擊「打開微信」按鈕,跳轉到WXApp以後,再點擊「Back to MyApp」,又回到MyApp了。閒着無聊就能夠反覆點擊這兩個按鈕來兩個應用間跳轉了,哈哈。
值得一說的是,這個URL Schemes並非惟一的。也就是說,多個應用之間設置的URL Schemes是能夠相同的。
那麼問題來了,假如兩個應用的URL Schemes相同的話,使用openURL:
方法會打開哪一個應用呢?
樓主親自用手機試了一下。
步驟是:
- 將MyApp安裝到手機上,點擊「打開微信」button,微信打開了。
- 而後將WXApp也安裝到手機上。再次點擊MyApp的「打開微信」button,結果打開的是WXApp。
結論:若是兩個應用有URL Schemes是相同的,後安裝的應用的URL Schemes會把早安裝的應用的URL Schems覆蓋掉。
沒錯,註冊了URL Schemes的應用,用safari瀏覽器也是能夠打開的。我就常常用這個來驗證應用是否設置了我想要的URL Schemes
在safari打開WXApp,直接在safari的地址欄輸入weixin://
,enter就能夠打開了
canOpenURL:
方法先判斷可否打開這個url,而後再用openURL
方法打開該URL的。這樣能夠帶來更好的用戶體驗。由於用戶不必定安裝了WXApp。假如用戶沒有安裝的話點擊「打開微信」button是沒有任何反應的。這時候咱們應該先判斷是否可以打開這個url(也就是判斷用戶有沒有安裝WXApp),沒有安裝的話就給個舒適提示,好比:「U四不四灑,沒安裝WXApp,怎麼打開啊!」。- (IBAction)openWXApp:(UIButton *)sender { // [self demo1]; [self demo2]; } //先判斷再打開WXApp - (void)demo2 { //建立一個url,這個url就是WXApp的url,記得加上:// NSURL *url = [NSURL URLWithString:@"weixin://"]; //先判斷是否能打開該url if ([[UIApplication sharedApplication] canOpenURL:url]) { //打開url [[UIApplication sharedApplication] openURL:url]; }else { //給個提示或者作點別的事情 NSLog(@"U四不四灑,沒安裝WXApp,怎麼打開啊!"); }
可是咱們發現用了canOpenURL:
方法以後,並無如咱們想像中打開了WXApp。一看,Xcode控制檯提示:
爲何會這樣呢?
由於iOS9的時候蘋果增強了權限,只有在info.plist文件中加入了URL Schemes白名單才能使用canOpenURL:
方法來判斷是否能打開該url。該白名單的上限是50個。也就是說,你最多隻能使用canOpenURL:
方法判斷50個URL Schemes。固然,日常咱們都用不了那麼多,就算是集成分享功能,50個確定夠了。
備註:只是對
canOpenURL:
方法有限制,openURL:
方法是沒有限制的。
言歸正傳,咱們須要在MyApp的info.plist裏面將weixin
設置爲白名單。
步驟:點擊info.plist->右鍵->Open As->Source Code->添加下面的代碼
<key>LSApplicationQueriesSchemes</key> <array> <string>weixin</string> </array>
這樣就能夠了。
URL Schemes除了能夠用來打開APP以外,還能夠用來在兩個App之間傳遞少許的數據。
在百度上搜索「ios」,會生成一個url,下面來以這個url來大概介紹url的組成。
url爲:https://www.baidu.com/s?ie=UTF-8&wd=ios
- https就是協議,也就是scheme
- www.baidu.com 是域名
- /s是路徑
- ?後面的是query,也就是查詢參數。這個url有兩個參數,分別是
ie=UTF-8
和wd=ios
咱們iOS的URL Schemes中也是差很少的。
並且,在openURL
的時候,若是url中帶有參數,只要URL Schemes是正確的,那一樣能夠打開App,並且,後面的參數也會帶到咱們打開的App那裏。
我們作個Demo就一目瞭然了。
在MyApp中,寫個demo3方法,url爲weixin://www.shixueqian.com/abc?title=hello&content=helloworld
- (IBAction)openWXApp:(UIButton *)sender { // [self demo1]; // [self demo2]; [self demo3]; } //使用URL Schemes傳遞數據 - (void)demo3 { //建立一個url,這個url就是WXApp的url,記得加上:// NSURL *url = [NSURL URLWithString:@"weixin://www.shixueqian.com/abc?title=hello&content=helloworld"]; //打開url [[UIApplication sharedApplication] openURL:url]; }
在WXApp的AppDelegate.m中,實現application: openURL:(NSURL *)url sourceApplication: annotation:
回調
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { NSLog(@"url=====%@ \n sourceApplication=======%@ \n annotation======%@", url, sourceApplication, annotation); return YES; }
run了以後,咱們發現,咱們依舊能夠經過點擊openURL:
方法打開WXApp。並且在WXApp被打開的時候,會執行application: openURL:(NSURL *)url sourceApplication: annotation:
回調方法。在這個回調方法中,咱們能夠獲得MyApp傳過來的url等信息。
控制檯打印以下:
完整的url信息都傳過來了,咱們就能夠利用這個url裏面的路徑和參數等信息了,想幹嗎就幹嗎。這就實現了從MyApp向WXApp傳遞數據了。
備註:
蘋果一共給了3個openURL的回調。
分別是:- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url NS_DEPRECATED_IOS(2_0, 9_0, "Please use application:openURL:options:") __TVOS_PROHIBITED; - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation NS_DEPRECATED_IOS(4_2, 9_0, "Please use application:openURL:options:") __TVOS_PROHIBITED; - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options NS_AVAILABLE_IOS(9_0); // no equiv. notification. return NO if the application can't open for some reason
爲何會有3個呢?這3個回調又有什麼區別?(爲方面講解,分別設置ABC3個回調)
- 3個回調的功能基本同樣,都是在別人經過URL Schemes打開應用的時候會執行的。
不一樣之處:- A回調是在iOS2.0的時候推出的,參數只有
url
。- B回到是在iOS4.2的時候推出的,參數有
url
sourceApplication
annotation
.- C回調是iOS9.0的時候推出的,參數有
url
options
。options
有下面幾個key// Keys for application:openURL:options: UIKIT_EXTERN NSString *const UIApplicationOpenURLOptionsSourceApplicationKey NS_AVAILABLE_IOS(9_0); // value is an NSString containing the bundle ID of the originating application UIKIT_EXTERN NSString *const UIApplicationOpenURLOptionsAnnotationKey NS_AVAILABLE_IOS(9_0); // value is a property-list typed object corresponding to what the originating application passed in UIDocumentInteractionController's annotation property UIKIT_EXTERN NSString *const UIApplicationOpenURLOptionsOpenInPlaceKey NS_AVAILABLE_IOS(9_0); // value is a bool NSNumber, set to YES if the file needs to be copied before use
- 這幾個回調是有優先級的。C>B>A。也就是說,若是你3個回調都實現了,那麼程序只會執行C回調。其餘回調是不會執行的。(固然,iOS9如下只會執行B回調)。
本篇文章的Demo已經上傳到GitHub上了https://github.com/shixueqian/OpenApp
歡迎觀看個人另外一篇文章,是這篇文章的進階版。
【iOS開發】仿微信分享功能
用通俗的語言,講述動人的代碼故事。
from:http://www.jianshu.com/p/0811ccd6a65d