目標
平常我們做iOS開發,會經常遇到打開其他的APP的功能。本篇文章講的就是打開別人的APP的一些知識。我們的目標是:
- 打開別人的APP
- 讓別人打開我們的APP
- iOS9的適配問題
- 使用URL Schemes傳遞數據
准備工作
- 建立一個名為OpenApp的工作空間,用來存放我們的兩個工程
建立這個工作空間主要是為了讓我們后面建立的兩個工程能在一個Xcode頁面上管理,方便講解和管理。挺簡單的,不清楚的可以看我之前的文章【iOS開發】在一個Xcode頁面建立多個工程

-
建立一個名為MyApp的iOS工程。這個MyApp是“我的app”,用來打開另一個APP的。
添加工程到我們剛才創建的OpenApp.xcworkspace。並且在工程的Main.storyboard添加一個button,待會兒我們會用來寫方法。
MyApp工程 -
建立一個名為WXApp的iOS工程。這個工程是我們模擬的“微信APP”,是被人打開的那個APP。
為了區分兩個應用,我們在Main.storyboard上加一個label,“我是微信App”。
在workspace建立WXApp工程

好了,准備工作就這么簡單。
打開別人的APP與讓別人打開我們的APP
想要打開別人的APP或者讓別人打開我們的APP,那就需要通過URL Schemes了。
什么是URL Schemes?
URL Schemes是蘋果給出的用來跳轉到系統應用或者跳轉到別人的應用的一種機制。同時還可以在應用之間傳數據。
通過對比網頁鏈接來理解 iOS 上的 URL Schemes,應該就容易多了。
URL Schemes 有兩個單詞:
- URL,我們都很清楚,http://www.apple.com
就是個 URL,我們也叫它鏈接或網址;- Schemes,表示的是一個 URL 中的一個位置——最初始的位置,即 ://
之前的那段字符。比如 http://www.apple.com
這個網址的 Schemes是 http。
根據我們上面對 URL Schemes 的使用,我們可以很輕易地理解,在以本地應用為主的 iOS 上,我們可以像定位一個網頁一樣,用一種特殊的 URL 來定位一個應用甚至應用里某個具體的功能。而定位這個應用的,就應該是這個應用的 URL 的 Schemes 部分,也就是開頭兒那部分。
在WXApp上設置一個URL Schemes
為了能讓別的App(包括我們剛才創建的MyApp)能夠打開WXApp,我們需要為WXApp添加一個URL Schemes。
步驟:選中WXApp工程->Info->URL Types->點擊“+”->在URL Schemes欄填上 weixin

備注:一個應用是可以有多個URL Schemes的。你可以再次點擊“+”來添加一個URL Schemes
我們看看info.plist文件里面是怎樣的。

然后我們run一下WXApp。(注意一下你run的target是哪個)

這樣,WXApp就向系統“注冊”了一個URL Schemes,其他的應用可以通過openurl:
方法來打開WXApp了。
MyApp打開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覆蓋掉。
在safari打開WXApp
沒錯,注冊了URL Schemes的應用,用safari瀏覽器也是可以打開的。我就經常用這個來驗證應用是否設置了我想要的URL Schemes
在safari打開WXApp,直接在safari的地址欄輸入weixin://
,enter就可以打開了


iOS9中的適配
- 配置URL Schemes白名單
其實在打開WXApp的時候,正常情況下,我們應該是先用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 Schems傳遞數據
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