IOS 應用 分享 擴充
iOS平台上想要實現不同App之間的內容分享一般有幾種常用方式:
第一種是通過AirDrop實現不同裝置的App之間文檔和資料的分享;
第二種是給每個App定義一個URL Scheme,通過訪問指定了URL Scheme的一個URL,實現直接存取一個APP;
第三種是通過UIDocumentInteractionController或者是UIActivityViewController這倆個iOS SDK中封裝好的類在App之間發送資料、分享資料和操作資料;
第四種是通過App Extension,在iOS 8的SDK中提供的擴充新特性實現跨App的資料操作和分享;
還有一種整合第三方SDK實現的有限個App的資料分享,比如社交平台(QQ,,新浪微博等)給我們提供的官方SDK,或者是整合了多個社交平台的ShareSDK組件和友盟分享組件等。
關於整合第三方SDK的使用,各大平台官網上都有詳細的文檔說明,同時推薦倆篇蘋果開發人員中心的文檔:Inter-App Communication和Document Interaction Programming Topics for iOS。其中之前有寫關於 如何通過UTI讓我們的App支援分享。
原理
我在“IOS UTI(統一類型標識符) 根據檔案尾碼開啟APP“這篇文章中,詳細地講解了一下UTI(Uniform Type Identifier),一套蘋果給我們提供用來在基於Cocoa和Cocoa Touch應用程式中識別實體內容類型的規範,而關於實現內容關聯的技術也正是基於這套規範。在iOS和Mac OS開發中,蘋果給我們提供了註冊文件類型的介面,而這種註冊的文件類型是全域的,系統中所有的應用程式和服務都可以偵測到。因此我們通過這個底層偵測,可以使用其他可選的第三方App來預覽我們的App中不支援的文檔,而且我們還可以通過這個介面在我們的App中開啟並處理第三方App的文檔。
如果我們的App可以處理某些類型的實體內容,那麼我們就可以在我們項目中的Info.plist檔案中進行註冊。關於使用哪種類型和UTI,就要參考我在“詳解蘋果提供的UTI(統一類型標識符)“這篇文章中的講解。當一個第三方App通過蘋果的底層偵測技術檢查有哪些App可以處理它所指定的內容類型時,如果我們的App已經註冊了這種類型,那麼我們的App表徵圖就會顯示在其中,並且作為我們自己的App的一個入口。
主要技術
主要應用到這種底層偵測的技術有iOS SDK中給我們提供的UIDocumentInteractionController、UIActivityViewController 和Quick Look 架構。此外,在iOS 8中,蘋果又給開發人員提供了App Extension,一種更高大上的方式在App之間的實現分享內容。關於UIDocumentInteractionController、UIActivityViewController、Quick Look 架構以及App Extension的細節,我計劃在後面的文章中詳細講解。這篇文章,我們主要是來談談如何註冊我們App可用的文件類型以及簡單使用我們的App來處理第三方App分享的內容。
註冊可用類型
我們需要在info.plist檔案中,添加一個新的屬性CFBundleDocumentTypes(實際上輸入的是”Document types”),這是一個數群組類型的屬性,意思就是我們可以同時註冊多個類型。而針對數組中的每一個元素,都有許多屬性可以指定,詳細的屬性列表我們可以從官方文檔上找到: Core Foundation Keys —- CFBundleDocumentTypes。這裡列舉我們在做iOS開發時常用的屬性:
CFBundleTypeName(“Icon File Name”)
字串類型,指定某種類型的別名,也就是用來指代我們規定的類型的別稱,一般為了保持唯一性,我們使用UTI來標識。
CFBundleTypeIconFiles
數群組類型,包含指定的png表徵圖的檔案名稱,指定代表某種類型的表徵圖,而表徵圖有具體的尺寸標識:
Device Sizes
iPad 64 x 64 pixels, 320 x 320 pixels
iPhone and iPod touch 22 x 29 pixels, 44 x 58 pixels (high resolution)
LSItemContentTypes(“Document Content Type UTIs”)
數群組類型,包含UTI字串,指定我們的應用程式所有可以識別的類型集合
LSHandlerRank(“Handler rank”)
字串類型,包含Owner,Default,Alternate,None四個可選值,指定對於某種類型的優先權層級,而Launcher Service會根據這個優先順序別來排列顯示的App的順序。優先順序別從高到低依次是Owner,Alternate,Default。None表示不接受這種類型。
瞭解了這些基本屬性,我們就需要在註冊App可用類型時,指定這些屬性,根據每個項目的需求不同,屬性值也不同。樣本作為一個參照:
在info中添加Document types
而當我們添加完所有屬性後,開始運行我們的程式,然後再回到我們的Info介面,就會看到Document types這個列表已經發生了變化,這就證明我們成功的註冊好了App可用的類型。
註冊成功,運行程式顯示的結果
開啟第三方應用
我們在上面的步驟中註冊好了我們的App可以識別的類型,現在我們可以開啟一個使用UIDocumentInteractionController或者是Quick Look架構來展示內容的第三方App,這裡以iPhone 上的QQ程式為例。
我們在上面的註冊步驟中,註冊的LSItemContentTypes僅包含了public.image這個UTI。所以我們先從QQ應用程式的我的檔案中,開啟不同類型的檔案進行對比,大家可以看我的檔案清單中包含倆種類型的檔案,一種是.jpg副檔名的圖片檔案,一種是.pdf副檔名的文檔檔案。
我的檔案清單
當我開啟一個圖片檔案進行預覽時,點擊其他應用開啟,就可以在App列表中看到我們的App表徵圖。簡單介紹一下這個頁面,第一行是蘋果在iOS 7之後給我們提供的使用AirDrZ喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vcNTaaVBob25loaJpUGFku/JpUG9kIFRvdWNoyeixuNauvOTNqLn9aUNsb3VkubLP7cTayN21xNK71ta3vcq9oaO12rb+0NDKx82ouf3OxLW1wODQzbnYwaq8vMr1yrax8LXEQXBwtcTB0LHtoaO12sj90NDKx82ouf3OxLW1udjBqry8yvXKtrHwtcRBY3Rpb261xMHQse2jrEFjdGlvbrHtyr621M7EtbW/yb340NC1xLLZ1/ejrMjnuLTWxqOstPLTobXIoaM8L3A+DQo8cD48aW1nIGFsdD0="這裡寫圖片描述" src="http://www.bkjia.com/uploads/allimg/160415/0419103921-3.png" title="\" />
開啟圖片,顯示ZSUTITestDemo App表徵圖
而如果我開啟PDF檔案的話,就看不到我們的App表徵圖。
開啟PDF檔案,看不到ZSUTITestDemo App表徵圖
程式回調
當我們通過上面步驟,成功地顯示了ZSUTITestDemo 的表徵圖之後,點擊表徵圖,我們就可以跳轉到ZSUTITestDemo應用中,而蘋果在iOS SDK中給我們提供的接收回調的方法在iOS 9之後做出了改變,因此我們需要針對不同的裝置版本做出改變:
#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0 - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation{ UINavigationController *navigation = (UINavigationController *)application.keyWindow.rootViewController; ViewController *displayController = (ViewController *)navigation.topViewController; [displayController.imageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:url]]]; [displayController.label setText:sourceApplication];return YES;}#else - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(nonnull NSDictionary *)options{UINavigationController *navigation = (UINavigationController *)application.keyWindow.rootViewController; ViewController *displayController = (ViewController *)navigation.topViewController; [displayController.imageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:url]]]; [displayController.label setText:[options objectForKey:UIApplicationOpenURLOptionsSourceApplicationKey]];return YES;}#endif