iPhone / iOS SDK 最酷的特性之一就是應用將其自身”綁定”到一個自定義 URL scheme 上,該 scheme 用于從瀏覽器或其他應用中啟動本應用。
注冊自定義 URL Scheme
?
注冊自定義 URL Scheme 的第一步是創建 URL Scheme — 在 Xcode Project Navigator 中找到并點擊工程 info.plist 文件。當該文件顯示在右邊窗口,在列表上點擊鼠標右鍵,選擇?Add Row:
?
向下滾動彈出的列表并選擇?URL types。
?
?
點擊左邊剪頭打開列表,可以看到?Item 0,一個字典實體。展開?Item 0,可以看到?URL Identifier,一個字符串對象。該字符串是你自定義的 URL scheme 的名字。建議采用反轉域名的方法保證該名字的唯一性,比如com.yourCompany.yourApp。
?
?
點擊?Item 0?新增一行,從下拉列表中選擇?URL Schemes,敲擊鍵盤回車鍵完成插入。
?
?
注意 URL Schemes 是一個數組,允許應用定義多個 URL schemes。
?
?
展開該數據并點擊?Item 0。你將在這里定義自定義 URL scheme 的名字。只需要名字,不要在后面追加 :// — 比如,如果你輸入 iOSDevApp,你的自定義 url 就是 iOSDevApp://
?
?
此時,整個定義如下圖:
?
?
雖然我贊同 Xcode 使用描述性的名字的目的,不過看到創建的實際的 key 也是非常有用的。這里有一個方便的技巧,右鍵點擊 plist 并選擇?Show Raw Keys/Values,就能看到以下效果:
?
?
還有另一種有用的輸出格式,XML,因為可以非常容易的看到字典和原始數組及其包括的實體的結構。點擊 plist 并選擇?Open As – Source Code:
?
?
從 Safari 中調用自定義 URL Scheme
?
定義了 URL scheme,我們可以運行一個快速測試來驗證應用是否如我們所期望的被調用。在這之前,我創建了一個準 UI 以辨別帶有自定義 URL 的應用。該應用只有一個 UILabel,帶有文本 “App With Custom URL”。下載源代碼(http://iosdevelopertips.com/downloads/#customURLScheme)
?
?
使用模擬器調用應用的步驟:
?
-
在 Xcode 中運行應用
-
一旦應用被安裝,自定義 URL scheme 就會被注冊
-
通過模擬器的硬件菜單中選擇 Home 來關閉應用
-
啟動 Safari
-
在瀏覽器地址欄輸入之前定義的 URL scheme(如下)
?
?
此時 Safari 將會關閉,應用會被帶回到前臺。祝賀你剛剛使用自定義 URL scheme 調用了一個 iPhone 應用。
?
從另一個 iPhone 應用中調用自定義 URL Scheme
?
讓我們看看如何從另一個應用中調用自定義 URL scheme。我又創建了一個非常簡單的 iPhone 應用,它只有一個 UILabel 和一個 UIButton — 前者顯示了一段信息,告訴你這個應用將要通過自定義 URL scheme 來調用另一個應用,按鈕則開始這個行為。下載源代碼(http://iosdevelopertips.com/downloads/#customURLScheme)
?
?
buttonPressed 方法中的代碼處理 URL 調用:
?
- (void)buttonPressed:(UIButton *)button
{
? NSString *customURL = @"iOSDevTips://";
?
? if ([[UIApplication sharedApplication]
? ? canOpenURL:[NSURL URLWithString:customURL]])
? {
? ? [[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
? }
? else
? {
? ? UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"URL error"
? ? ? ? ? ? ? ? ? ? ? ? ? message:[NSString stringWithFormat:
? ? ? ? ? ? ? ? ? ? ? ? ? ? @"No custom URL defined for %@", customURL]
? ? ? ? ? ? ? ? ? ? ? ? ? delegate:self cancelButtonTitle:@"Ok"
? ? ? ? ? ? ? ? ? ? ? ? ? otherButtonTitles:nil];
? ? [alert show];
? }
}
?
第5行代碼檢查自定義 URL 是否被定義,如果定義了,則使用 shared application 實例來打開 URL (第 8 行)。openURL:方法啟動應用并將 URL 傳入應用。在此過程中,當前的應用被退出。
?
通過自定義 URL Scheme 向應用傳遞參數
?
有時你需要通過自定義 URL 向應用中傳遞參數。讓我們看看該如何完成這個工作。
?
NSURL 作為從一個應用調用另一個的基礎,遵循?RFC 1808(https://tools.ietf.org/html/rfc1808)?(Relative Uniform Resource Locators) 標準。 因此你所熟悉的基于網頁內容的 URL 格式在這里也適用。
?
在自定義了 URL scheme 的應用中,app delegate 必須實現以下方法:
?
- (BOOL)application:(UIApplication *)application
? openURL:(NSURL *)url
? sourceApplication:(NSString *)sourceApplication
? annotation:(id)annotation
?
從一個應用傳遞參數到另一個的訣竅是通過 URL。例如,假設我們使用以下的 URL scheme,想傳遞一個名為 “token”的參數和一個標識注冊狀態的標志,我們可以像這樣創建一個 URL:
?
NSString *customURL = @"iOSDevTips://?token=123abct®istered=1";
?
在 web 開發中,字符串??token=123abct®istered=1?被稱作查詢詢串(query string)。
?
在被調用(設置了自定義 URL)的應用的 app delegate 中,獲取參數的代碼如下:
?
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
? ? ? ? sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
? NSLog(@"Calling Application Bundle ID: %@", sourceApplication);
? NSLog(@"URL scheme:%@", [url scheme]);
? NSLog(@"URL query: %@", [url query]);
?
? return YES;
}
?
以上代碼在應用被調用時的輸出為:
?
?
Calling Application Bundle ID: com.3Sixty.CallCustomURL
URL scheme:iOSDevTips
URL query: token=123abct®istered=1
?
注意 “Calling Application Bundle ID”,你可以用這個來確保只有你定義的應用可以與你的應用直接交互。
?
讓我們改變一下代碼,來驗證發起調用的應用的 Bundle ID 是否合法:
?
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
? ? ? ? sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
? // Check the calling application Bundle ID
? if ([sourceApplication isEqualToString:@"com.3Sixty.CallCustomURL"])
? {
? ? NSLog(@"Calling Application Bundle ID: %@", sourceApplication);
? ? NSLog(@"URL scheme:%@", [url scheme]);
? ? NSLog(@"URL query: %@", [url query]);
?
? ? return YES;
? }
? else
? ? return NO;
}
?
有一點要特別注意,你不能阻止其他應用通過自定義 URL scheme 調用你的應用,然而你可以跳過后續的操作并返回 NO,就像上面的代碼那樣。也就是說,如果你想阻止其它應用調用你的應用,創建一個與眾不同的 URL scheme。盡管這不能保證你的應用不會被調用,但至少大大降低了這種可能性。
?