iOS文檔交互(About Document Interaction)


????最近在做一個(gè)文檔管理的個(gè)人項(xiàng)目時(shí)碰到了一些關(guān)于這樣那樣的iOS文檔交互處理的問題,在這里做一個(gè)小結(jié)??

目錄:

  1. iOS中的文檔交互簡介
  2. 如何預(yù)覽和打開文檔
  3. 打通與其他app之間的文檔交互--注冊文件支持類型
  4. 打開從其他app傳過來的文檔
  5. Quick Look Framework的使用
  6. 小結(jié)

1.iOS中的文檔交互簡介


????iOS中為開發(fā)者提供了一種即便app并不支持某些文件,也可以打開預(yù)覽該文件的技術(shù)。

????iOS中還提供了一個(gè)關(guān)聯(lián)文件類型的系統(tǒng)注冊表,如果你的app注冊了相關(guān)文件的類型,那么系統(tǒng)會(huì)允許你的app可以處理從其他應(yīng)用程序中打開的文件;同時(shí)支持處理airDrop傳輸過來的文件。
?這些強(qiáng)大的技術(shù)包括 UIKit 中的UIDocumentInteractionControllerQuick Look framework框架。

2.如何預(yù)覽和打開文檔


????任何app都可以使用文檔交互控制器進(jìn)行文件操作。相關(guān)交互場景可能發(fā)生在需要從網(wǎng)絡(luò)下載文件進(jìn)而顯示預(yù)覽的app里。例如,電子郵件類型的app使用文檔交互控制器預(yù)覽或打開某一封郵件附件中的文件。

????除了預(yù)覽和打開某些文件的需求外,還有一些文件交互是發(fā)生在文件共享場景下的。例如,從其他app中通過系統(tǒng)分享或者airdrop分享某些特定類型的文件進(jìn)行處理。

使用UIDocumentInteractionController進(jìn)行文件交互


????初始化一個(gè)UIDocumentInteractionController實(shí)例,并設(shè)置代理,由其代理方法可以獲知相關(guān)視圖的信息以及方便在與用戶交互時(shí)進(jìn)行一些額外的操作。簡單的初始化代碼如下:

?- (UIDocumentInteractionController *) setupControllerWithURL: (NSURL) fileURL
?    usingDelegate: (id <UIDocumentInteractionControllerDelegate>) interactionDelegate {
 
?    UIDocumentInteractionController *interactionController =
        [UIDocumentInteractionController interactionControllerWithURL: fileURL];
?    interactionController.delegate = interactionDelegate;
 
?    return interactionController;
?}

????UIDocumentInteractionController中提供了一些關(guān)于文件名、文件類型以及URL的屬性,可以方便開發(fā)者獲取文件相關(guān)信息。

UIDocumentInteractionController的兩種操作


????UIDocumentInteractionController提供了兩種操作文件的方式,一種是文件預(yù)覽,效果圖如下所示:

文件預(yù)覽.png

????預(yù)覽和打開文件可以使用以下方法:

// Bypasses the menu and opens the full screen preview window for the item at URL.  Returns NO if the item could not be previewed.
// Note that you must implement the delegate method documentInteractionControllerViewControllerForPreview: to preview the document.
- (BOOL)presentPreviewAnimated:(BOOL)animated;

????如果不需要打開文件只是進(jìn)行文件分享,則可以使用以下方法:

// This is the default method you should call to give your users the option to quick look, open, or copy the document.
// Presents a menu allowing the user to Quick Look, open, or copy the item specified by URL.
// This automatically determines the correct application or applications that can open the item at URL.
// Returns NO if the options menu contained no options and was not opened.
// Note that you must implement the delegate method documentInteractionControllerViewControllerForPreview: to get the Quick Look menu item.
- (BOOL)presentOptionsMenuFromRect:(CGRect)rect inView:(UIView *)view animated:(BOOL)animated;

????效果圖如下:

文件分享.png

?demo戳這里查看

3. 打通與其他app之間的文檔交互--注冊文件支持類型


????上面介紹了app內(nèi)打開和分享文件的使用,如果你的app支持打開某些特殊類型的文件,并允許其他app通過文件交互技術(shù)將文件交給你的app處理的話,你可以在系統(tǒng)注冊表中注冊相關(guān)文件支持類型。

????如果想要聲明對某些文件類型的支持,可以在Info.plist中添加CFBundleDocumentTypes鍵值對。系統(tǒng)會(huì)在注冊表中添加該信息,然后其他app就可以通過文檔交互控制器進(jìn)行訪問了。

????CFBundleDocumentTypes的值是一個(gè)字典數(shù)組,數(shù)組中的每一個(gè)字典都包含了一個(gè)特定文檔類型的相關(guān)信息。
????正常情況下文檔的類型和這些特定的文件類型是一一對應(yīng)的,但是如果你的應(yīng)用程序處理的文件類型不止一個(gè),那么可以將這些文件類型組合在一起,作為單個(gè)文檔類型來處理。

????例如,如果你的本地文檔同時(shí)包含一個(gè)舊的文件格式和一個(gè)新的文件格式,比較典型的像.doc.docx,那么就可以將它們組合在同一個(gè)文檔類型中。這樣,舊的文件格式和新的文件格式就會(huì)被當(dāng)成同一種文檔類型,并且使用相同的方式進(jìn)行處理。

CFBundleDocumentTypes中每個(gè)字典都包括以下key:
?- CFBundleTypeName--------------文件類型的名字
?- CFBundleTypeIconFiles---------用于作文件icon的圖片名數(shù)組
?- LSItemContentTypes------------當(dāng)前所支持的文件類型的UTI類型的字符串?dāng)?shù)組
?- LSHandlerRank-----------------標(biāo)示當(dāng)前app對該文件類型的權(quán)限

????其中LSItemContentTypes中的UTI字符串是真正確定某個(gè)文件類型的唯一標(biāo)示。系統(tǒng)聲明的UTI可以點(diǎn)這里查看,非常多

????而LSHandlerRank的權(quán)限共分為以下幾種:
?- Owner--------------app為該文件類型的主要?jiǎng)?chuàng)建者和擁有者
?- Default------------app為該文件類型的開啟者,如果沒有指定權(quán)限則默認(rèn)為Default
?- Alternate----------app為該文件類型的二級(jí)查看器
?- None---------------app不會(huì)被選擇打開這個(gè)類型的文件,但是它可以接受這種類型的文件

????接收的文件會(huì)被存儲(chǔ)在app的Document目錄的indox文件夾下。

????下面是一個(gè)pdf文件類型聲明的簡單示例:

<dict>
   <key>CFBundleTypeName</key>
   <string>PDF文件</string>
   <key>CFBundleTypeIconFiles</key>
       <array>
           <string>MySmallIcon.png</string>
           <string>MyLargeIcon.png</string>
       </array>
   <key>LSItemContentTypes</key>
       <array>
           <string>com.adobe.pdf</string>
       </array>
   <key>LSHandlerRank</key>
   <string>Owner</string>
</dict>

????當(dāng)app添加文件類型支持之后,用戶使用文檔交互控制器從其他app分享相關(guān)文件類型時(shí),就會(huì)發(fā)現(xiàn)自己的app在可操作列表里面了。如下圖:

文件類型支持.png

?當(dāng)然如果用戶是通過airDrop進(jìn)行文件傳輸,app同樣會(huì)出現(xiàn)在可操作列表里面,如下圖:

airDrop接收列表.png

4. 打開從其他app傳過來的文檔


????當(dāng)app添加相關(guān)文件類型支持之后,系統(tǒng)可能要求您的應(yīng)用程序打開一個(gè)特定的文件并將其呈現(xiàn)給用戶。那么app該如何監(jiān)聽傳過來的文件呢?

????這里分兩種情況,當(dāng)app處于未啟動(dòng)狀態(tài)時(shí),可以通過以下方法獲取相關(guān)信息:

application:willFinishLaunchingWithOptions:
 或者 
application:didFinishLaunchingWithOptions:

????而文件相關(guān)信息包含在上面?zhèn)z個(gè)方法的options參數(shù)字典中,你可以通過查看options字典中的以下key來獲取相關(guān)信息。
?- UIApplicationLaunchOptionsURLKey------------------包含了該文件的NSURL對象
?- UIApplicationLaunchOptionsSourceApplicationKey----包含了文件傳輸源app的bundleId
?- UIApplicationLaunchOptionsAnnotationKey-----------包含了一個(gè)文件傳輸源app傳遞過來的關(guān)于該文件的屬性列表。

????而當(dāng)app處于啟動(dòng)狀態(tài)時(shí),則可以通過以下方法獲取到傳輸來的文檔相關(guān)信息。

    func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
        return true
    }

小貼士:
????如果app只是支持預(yù)覽某些文件,而不必保存該文件,則可以在以上方法中獲取到文件存儲(chǔ)到本地的路徑,將其刪除。

5. Quick Look Framework的使用


????當(dāng)文件存儲(chǔ)到本地之后,為了獲得對文件預(yù)覽的更多控制,可以直接使用 Quick Look Framework

????該框架最主要的類是QLPreviewControllerQLPreviewController提供了代理QLPreviewControllerDelegate響應(yīng)用戶對文件的相關(guān)操作,并提供了一個(gè)數(shù)據(jù)源代理QLPreviewControllerDataSource,設(shè)置預(yù)覽文件的相關(guān)源數(shù)據(jù)。

????QLPreviewController可以使用UINavigationControllerpush出來,也可以使用模態(tài)的方式彈出。并且使用模態(tài)彈出的時(shí)候還會(huì)有更多操作手勢。

????QLPreviewController支持以下文件格式的預(yù)覽:
?- 蘋果自家的iWork相關(guān)文檔(Pages、Numbers、Keynote)
?- Microsoft辦公文檔(office97以及之后的版本)
?- PDF文件
?- RTF文檔
?- 圖片
?- UTI標(biāo)示符和public.text符合的文本文件
?- csv文件

????QLPreviewController還支持同時(shí)預(yù)覽多個(gè)文件,支持多文件的左右切換,由其數(shù)據(jù)源控制。

6. 小結(jié)


????在筆者學(xué)習(xí)過程中也發(fā)現(xiàn)了一些關(guān)于UIDocumentInteractionControllerQuick Look framework這些用于進(jìn)程間通信的remote viewController的限制,比如navtoolbar及其action的無法自定義。

????關(guān)于它們的自定義,筆者現(xiàn)在的做法是子類化UIDocumentInteractionControllerQuick Look framework,在控制器的生命周期方法中獲取其navtoolbar,修改navtoolbar的相關(guān)屬性以達(dá)到自定義的需求。

????除了以上提到的文檔交互相關(guān)內(nèi)容,蘋果還提供了
Document Provider Extensions
,它允許其他app使用文檔選擇器來訪問文檔。
????相關(guān)的,開發(fā)者也可以在自己的app中集成iCloudKit,進(jìn)一步加深用戶的文檔交互操作。(最新出的還有一個(gè)PDFKit,這幾個(gè)有時(shí)間筆者會(huì)補(bǔ)上???)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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