實現iOS app之間的內容分享

前言

咱們在iOS平臺上想要實現不一樣App之間的內容分享通常有幾種經常使用方式:html

  1. 第一種是經過AirDrop實現不一樣設備的App之間文檔和數據的分享;ios

  2. 第二種是給每一個App定義一個URL Scheme,經過訪問指定了URL Scheme的一個URL,實現直接訪問一個APP;git

  3. 第三種是經過UIDocumentInteractionController或者是UIActivityViewController這倆個iOS SDK中封裝好的類在App之間發送數據、分享數據和操做數據;github

  4. 第四種是經過App Extension,在iOS 8的SDK中提供的擴展新特性實現跨App的數據操做和分享;數組

  5. 還有一種集成第三方SDK實現的有限個App的數據分享,好比社交平臺(QQ,微信,新浪微博等)給咱們提供的官方SDK,或者是集成了多個社交平臺的ShareSDK組件和友盟分享組件等。微信

關於集成第三方SDK的使用,各大平臺官網上都有詳細的文檔說明,所以咱們這系列文章主要是來談談蘋果原生提供的基於iOS SDK的分享技術,同時推薦倆篇蘋果開發者中心的文檔:Inter-App CommunicationDocument Interaction Programming Topics for iOS。咱們的第一篇文章就談一下如何經過UTI讓咱們的App支持分享。app

原理

我在「詳解蘋果提供的UTI(統一類型標識符)「這篇文章中,詳細地講解了一下UTI(Uniform Type Identifier),一套蘋果給咱們提供用來在基於Cocoa和Cocoa Touch應用程序中識別實體內容類型的規範,而關於實現內容關聯的技術也正是基於這套規範。在iOS和Mac OS開發中,蘋果給咱們提供了註冊文檔類型的接口,而這種註冊的文檔類型是全局的,系統中全部的應用程序和服務均可以偵測到。所以咱們經過這個底層偵測,可使用其餘可選的第三方App來預覽咱們的App中不支持的文檔,並且咱們還能夠經過這個接口在咱們的App中打開並處理第三方App的文檔。框架

若是咱們的App能夠處理某些類型的實體內容,那麼咱們就能夠在咱們項目中的Info.plist文件中進行註冊。關於使用哪一種類型和UTI,就要參考我在「詳解蘋果提供的UTI(統一類型標識符)「這篇文章中的講解。當一個第三方App經過蘋果的底層偵測技術檢查有哪些App能夠處理它所指定的內容類型時,若是咱們的App已經註冊了這種類型,那麼咱們的App圖標就會顯示在其中,而且做爲咱們本身的App的一個入口。ide

主要技術

主要應用到這種底層偵測的技術有iOS SDK中給咱們提供的UIDocumentInteractionControllerUIActivityViewController Quick Look 框架。此外,在iOS 8中,蘋果又給開發者提供了App Extension,一種更高大上的方式在App之間的實現分享內容。關於UIDocumentInteractionControllerUIActivityViewController Quick Look 框架以及App Extension的細節,我計劃在後面的文章中詳細講解。這篇文章,咱們主要是來談談如何註冊咱們App可用的文檔類型以及簡單使用咱們的App來處理第三方App分享的內容ui

註冊可用類型

咱們須要在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的順序。優先級別從高到低依次是OwnerAlternate,DefaultNone表示不接受這種類型。

瞭解了這些基本屬性,咱們就須要在註冊App可用類型時,指定這些屬性,根據每一個項目的需求不一樣,屬性值也不一樣。具體的註冊請參照個人GitHub上的項目:SeraZheng---ZSUTITest。下圖示例做爲一個參照:
在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以後給咱們提供的使用AirDropiPhoneiPadiPod Touch設備之間經過iCloud共享內容的一種方式。第二行是經過文檔類型關聯技術識別的App的列表。第三行是經過文檔關聯技術識別的Action的列表,Action表示對文檔可進行的操做,如複製,打印等。
打開圖片,顯示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<NSString *,id> *)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

Demo示例能夠從GitHub項目上參照代碼:SeraZheng---ZSUTITest。當點擊ZSUTITestDemo程序圖標回到調用代碼中,咱們能夠在這裏作各類咱們想作的事,如上傳圖片、預覽圖片、操做圖片等等。我只對圖片作了簡單的預覽顯示,而後顯示文件的源程序的Bundle Identifier,示例以下圖:

顯示圖片和源程序的Bundle Identifier

相關文章
相關標籤/搜索