UIDocumentInteractionController之程序間文檔共享

iOS中的沙盒可以讓平臺(tái)更加的安全褐奥,這也是沙盒給用戶帶來的最主要好處。不過由于沙盒的嚴(yán)格限制翘簇,導(dǎo)致程序之間共享數(shù)據(jù)比較麻煩撬码。一般在程序間共享文檔可以通過UIDocumentInteractionController類實(shí)現(xiàn)通訊。它支持在你的app中用其他app預(yù)覽和顯示文檔版保。同時(shí)也支持文件關(guān)聯(lián)呜笑,允許其他app通過你的程序打開文件夫否。這些技術(shù)包括了UIKit中提供的UIDocumentInteractionController類(UIDocumentInteractionController Class Reference),以及Quick Look框架(Quick Look Framework Reference)叫胁。

本文將就如何在應(yīng)用之間進(jìn)行文件共享進(jìn)行基本探究凰慈。還請(qǐng)大牛勿噴。

蘋果官方文檔

效果圖

文件共享
跨APP傳文件

預(yù)覽文檔和呈現(xiàn)選項(xiàng)菜單

如果你的app需要打開它不支持的文件(PDF文件驼鹅、圖像文件微谓,等等),或者需要將app的文件傳輸給另外一個(gè)允許接收此類型文件的app時(shí)输钩〔蛐停可以使用文件交互控制器(UIDocumentInteractionController類的實(shí)例)為用戶提供可接收程序來處理文件,說的簡單點(diǎn)就是通過Quick Look框架判斷文檔是否能被另一個(gè)app打開和預(yù)覽买乃。

UIDocumentInteractionController在iOS3.2中就已經(jīng)存在了姻氨,使用起來非常靈活,功能也比較強(qiáng)大剪验。它除了支持同設(shè)備上app之間的文檔共享外肴焊,還可以實(shí)現(xiàn)文檔的預(yù)覽、打印功戚、發(fā)郵件以及復(fù)制抖韩。

要使用一個(gè)文件交互控制器(UIDocumentInteractionController類的實(shí)例),需要以下步驟:

  1. 為每個(gè)你想打開的文件創(chuàng)建一個(gè)UIDocumentInteractionController類的實(shí)例
  2. 實(shí)現(xiàn)UIDocumentInteractionControllerDelegate代理
  3. 顯示預(yù)覽窗口/顯示菜單疫铜。

一茂浮、創(chuàng)建實(shí)例

DocumentInteraction Controller使用靜態(tài)方法interactionControllerWithURL創(chuàng)建實(shí)例,這個(gè)方法使用一個(gè)NSURL作為參數(shù)壳咕。

//創(chuàng)建實(shí)例
NSURL *filePath = [NSURL fileURLWithPath:path];

UIDocumentInteractionController *documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]];

二席揽、顯示預(yù)覽窗口

Document Interaction Controller對(duì)象使用presentPreviewAnimated方法彈出一個(gè)全屏的文檔預(yù)覽窗口。

BOOL b = [documentController presentPreviewAnimated:YES];

三谓厘、顯示菜單

如果你不想在本應(yīng)用里面打開文件幌羞,那么可以通過第三方應(yīng)用打開預(yù)覽文件。通過OptionsMenu(選項(xiàng)菜單)竟稳,顯示能夠接收該類型文件的應(yīng)用属桦,由用戶選擇相應(yīng)的操作。

顯示菜單可以使用下列方法:

- presentOptionsMenuFromRect:inView:animated:
- presentOptionsMenuFromBarButtonItem:animated:
- presentOpenInMenuFromRect:inView:animated:
- presentOpenInMenuFromBarButtonItem:animated:

這些方法都是類似的他爸,只是顯示位置有區(qū)別而已聂宾。以下代碼演示其中一個(gè)方法的使用。

CGRect navRect = self.navigationController.navigationBar.frame;
navRect.size = CGSizeMake(1500.0f, 40.0f);
[documentController presentOptionsMenuFromRect:navRect
                                        inView:self.view
                                      animated:YES];

四诊笤、使用委托

如果你顯示一個(gè)Document Interaction Controller 系谐,則必需要為delegate屬性用指定一個(gè)委托。讓委托告訴DocumentInteraction Controller如何顯示。

documentController.delegate = self;

委托對(duì)象需要實(shí)現(xiàn)一系列委托方法纪他,最常見的包括:

- documentInteractionControllerViewControllerForPreview:
- documentInteractionControllerViewForPreview:
- documentInteractionControllerRectForPreview:

這3個(gè)方法在用戶點(diǎn)擊“快速查看”菜單時(shí)依次調(diào)用鄙煤。

- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller {
    return self;
}
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller {
    return self.view;
}

- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller {
  return self.view.frame;
 }
 
//點(diǎn)擊預(yù)覽窗口的“Done”(完成)按鈕時(shí)調(diào)用
- (void)documentInteractionControllerDidEndPreview:(UIDocumentInteractionController *)controller {
}

功能一:分享文件

- (void)shareFile {
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"皮卡丘"
                                                          ofType:@"jpeg"];
                                                          
    //創(chuàng)建實(shí)例
    UIDocumentInteractionController *documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:filePath]];
    
    //設(shè)置代理
    documentController.delegate = self;
    BOOL canOpen = [documentController presentOpenInMenuFromRect:CGRectZero
                                                          inView:self.view
                                                        animated:YES];
    if (!canOpen) {
        NSLog(@"沒有程序可以打開要分享的文件");
    }
}

功能二:預(yù)覽文件(注冊(cè)應(yīng)用程序支持的文件類型)

- (void)preview {
    if (!_path) {
        return;
    }

    NSURL *fileURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", [self getURL], [_path lastPathComponent]]];
    
    //創(chuàng)建實(shí)例
    UIDocumentInteractionController *documentController =
    [UIDocumentInteractionController
     interactionControllerWithURL:fileURL];
     
    //設(shè)置代理
    documentController.delegate = self;

    [documentController presentPreviewAnimated:YES];
}

配置Info.plist文件

如果你的程序能夠打開某種文件,你可以向系統(tǒng)進(jìn)行注冊(cè)茶袒。方便其他程序通過 iOS 的document interaction技術(shù)提供給用戶一個(gè)選擇梯刚,從而調(diào)用你的程序處理這些文件。

這需要在程序的Info.plist文件中添加CFBundleDocumentTypes鍵(查看CoreFoundation Keys)薪寓。

系統(tǒng)將該鍵中包含的內(nèi)容進(jìn)行登記亡资,這樣其他程序就可以通過document interaction controller訪問到這些信息。

CFBundleDocumentTypes鍵是一個(gè)dictionary數(shù)組预愤,每個(gè)dictionary表示了一個(gè)指定的文檔類型沟于。一個(gè)文檔類型通常與某種文件類型是一一對(duì)應(yīng)的咳胃。

但是植康,如果你的程序?qū)Χ鄠€(gè)文件類型采用同樣的處理方式,你也可以把這些類型都分成一個(gè)組展懈,統(tǒng)一視作一個(gè)文檔類型销睁。例如,你的程序中使用到的本地文檔類型存崖,有一個(gè)是舊格式的冻记,還有一個(gè)新格式(似乎是影射微軟office文檔),則你可以將二者分成一組来惧,都放到同一個(gè)文檔類型下冗栗。這樣,舊格式和新格式的文件都將顯示為同一個(gè)文檔類型供搀,并以同樣的方式打開隅居。

CFBundleDocumentTypes數(shù)組中的每個(gè) dictionary 可能包含以下鍵:

  • CFBundleTypeName

指定文檔類型名稱。

  • CFBundleTypeIconFiles

是一個(gè)數(shù)組葛虐,包含多個(gè)圖片文件名胎源,用于作為該文檔的圖標(biāo)。

  • LSItemContentTypes

是一個(gè)數(shù)組屿脐,包含多個(gè)UTIUniform Type Identifiers】類型的字符串涕蚤。UTI類型是本文檔類型(組)所包含的文件類型。

  • LSHandlerRank

表示應(yīng)用程序是“擁有”還是僅僅是“打開”這種類型而已的诵。

下表列出了Info.plist中的一個(gè)CFBundleTypeName官方示例万栅。

  1. 自定義文件格式的文檔類型
<dict>
  <key>CFBundleTypeName</key>
  <string>My File Format</string>
  <key>CFBundleTypeIconFiles</key>
      <array>
          <string>MySmallIcon.png</string>
          <string>MyLargeIcon.png</string>
      </array>
  <key>LSItemContentTypes</key>
      <array>
          <string>com.example.myformat</string>
      </array>
  <key>LSHandlerRank</key>
  <string>Owner</string>
</dict>
  1. 自己程序配置文件
<key>CFBundleDocumentTypes</key>
   <array>
       <dict>
           <key>CFBundleTypeName</key>
           <string>com.myapp.common-data</string>
           <key>LSItemContentTypes</key>
           <array>
               <string>com.microsoft.powerpoint.ppt</string>
               <string>public.item</string>
               <string>com.microsoft.word.doc</string>
               <string>com.adobe.pdf</string>
               <string>com.microsoft.excel.xls</string>
               <string>public.image</string>
               <string>public.content</string>
               <string>public.composite-content</string>
               <string>public.archive</string>
               <string>public.audio</string>
               <string>public.movie</string>
               <string>public.text</string>
               <string>public.data</string>
           </array>
       </dict>
   </array>

打開支持的文件類型

你可以在應(yīng)用程序委托的application:didFinishLaunchingWithOptions:方法中獲得該文件的信息。如果你的程序要處理某些自定義的文件類型西疤,你必須實(shí)現(xiàn)這個(gè)委托方法(而不是applicationDidFinishLaunching: 方法) 并用這個(gè)方法啟動(dòng)應(yīng)用程序申钩。

application:didFinishLaunchingWithOptions:方法的option參數(shù)包含了要打開的文件的相關(guān)信息。尤其需要在程序中關(guān)心下列鍵:

  • UIApplicationLaunchOptionsURLKey

包含了該文件的NSURL瘪阁。

  • UIApplicationLaunchOptionsSourceApplicationKey

包含了發(fā)送請(qǐng)求的應(yīng)用程序的 Bundle ID撒遣。

  • UIApplicationLaunchOptionsAnnotationKey

包含了源程序向目標(biāo)程序傳遞的與該文件相關(guān)的屬性列表對(duì)象邮偎。

如果UIApplicationLaunchOptionsURLKey鍵存在,你的程序應(yīng)當(dāng)立即用該 URL 打開該文件并將內(nèi)容呈現(xiàn)給用戶义黎。其他鍵可用于收集與打開的文件相關(guān)的參數(shù)和信息禾进。

如果你的應(yīng)用程序處于活躍狀態(tài),此時(shí)application:didFinishLaunchingWithOptions:方法是不會(huì)被調(diào)用的廉涕。需要實(shí)現(xiàn)application:openURL:options:方法

【以下是本人的寫法】

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    _vc = [[ViewController alloc] init];
    UINavigationController *nav    = [[UINavigationController alloc] initWithRootViewController:_vc];
    
    self.window                    = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor    = [UIColor whiteColor];
    self.window.rootViewController = nav;
    [self.window makeKeyAndVisible];
    
    if (launchOptions) {
        NSString *str = [NSString stringWithFormat:@"\n發(fā)送請(qǐng)求的應(yīng)用程序的 Bundle ID:%@\n\n文件的NSURL:%@\n\n文件相關(guān)的屬性列表對(duì)象:%@",
                         launchOptions[UIApplicationLaunchOptionsSourceApplicationKey],
                         launchOptions[UIApplicationLaunchOptionsURLKey],
                         launchOptions[UIApplicationLaunchOptionsSourceApplicationKey]];
        
        [[[UIAlertView alloc] initWithTitle:@""
                                    message:str
                                   delegate:nil
                          cancelButtonTitle:@"確定"
                          otherButtonTitles:nil, nil] show];
        
        _vc.path = [launchOptions[UIApplicationLaunchOptionsURLKey] description];
        [_vc preview];
    }
    return YES;
}

- (BOOL)application:(UIApplication *)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<NSString *,id> *)options {
    if (options) {
        NSString *str = [NSString stringWithFormat:@"\n發(fā)送請(qǐng)求的應(yīng)用程序的 Bundle ID:%@\n\n文件的NSURL:%@", options[UIApplicationOpenURLOptionsSourceApplicationKey], url];
        
        [[[UIAlertView alloc] initWithTitle:@""
                                    message:str
                                   delegate:nil
                          cancelButtonTitle:@"確定"
                          otherButtonTitles:nil, nil] show];

        _vc.path = [url description];
        [_vc preview];
    }
    return YES;
}

再一次感謝您花費(fèi)時(shí)間閱讀這篇文章泻云!

微博: @Danny_呂昌輝
博客: SuperDanny

2015 年 12月 26日

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市狐蜕,隨后出現(xiàn)的幾起案子宠纯,更是在濱河造成了極大的恐慌,老刑警劉巖层释,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婆瓜,死亡現(xiàn)場離奇詭異,居然都是意外死亡贡羔,警方通過查閱死者的電腦和手機(jī)廉白,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來乖寒,“玉大人猴蹂,你說我怎么就攤上這事¢灌遥” “怎么了磅轻?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長逐虚。 經(jīng)常有香客問我聋溜,道長,這世上最難降的妖魔是什么痊班? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任勤婚,我火速辦了婚禮,結(jié)果婚禮上涤伐,老公的妹妹穿的比我還像新娘馒胆。我一直安慰自己,他們只是感情好凝果,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布祝迂。 她就那樣靜靜地躺著,像睡著了一般器净。 火紅的嫁衣襯著肌膚如雪型雳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音纠俭,去河邊找鬼沿量。 笑死,一個(gè)胖子當(dāng)著我的面吹牛冤荆,可吹牛的內(nèi)容都是我干的朴则。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼钓简,長吁一口氣:“原來是場噩夢啊……” “哼乌妒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起外邓,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤撤蚊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后损话,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侦啸,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年席镀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匹中。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夏漱。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡豪诲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挂绰,到底是詐尸還是另有隱情屎篱,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布葵蒂,位于F島的核電站交播,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏践付。R本人自食惡果不足惜秦士,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望永高。 院中可真熱鬧隧土,春花似錦、人聲如沸命爬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饲宛。三九已至皆愉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背幕庐。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來泰國打工久锥, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人异剥。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓特纤,卻偏偏與公主長得像抛姑,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理较鼓,服務(wù)發(fā)現(xiàn),斷路器魄宏,智...
    卡卡羅2017閱讀 134,657評(píng)論 18 139
  • UIDocumentInteractionController之程序間文檔共享
    RunningMan_Fly閱讀 492評(píng)論 0 0
  • 見www.reibang.com/p/59279b018217 Application can be killed...
    heatbeats閱讀 3,051評(píng)論 0 0
  • iOS中的沙盒可以讓平臺(tái)更加的安全亮蛔,這也是沙盒給用戶帶來的最主要好處痴施。不過由于沙盒的嚴(yán)格限制,導(dǎo)致程序之間共享數(shù)據(jù)...
    閑云清煙閱讀 620評(píng)論 0 0
  • 我拿起麥克風(fēng) 唱完這首歌 我故意唱錯(cuò)一個(gè)音 希望你能聽得出究流。
    留子堯閱讀 173評(píng)論 0 2