iOS文档交互(About Document Interaction)


    最近在做一个文档管理的个人项目时碰到了一些关于这样那样的iOS文档交互处理的问题,在这里做一个小结

目录:

  1. iOS中的文档交互简介
  2. 如何预览和打开文档
  3. 打通与其他app之间的文档交互--注册文件支持类型
  4. 打开从其他app传过来的文档
  5. Quick Look Framework的使用
  6. 小结

1.iOS中的文档交互简介


    iOS中为开发者提供了一种即便app并不支持某些文件,也可以打开预览该文件的技术。

    iOS中还提供了一个关联文件类型的系统注册表,如果你的app注册了相关文件的类型,那么系统会允许你的app可以处理从其他应用程序中打开的文件;同时支持处理airDrop传输过来的文件。
 这些强大的技术包括 UIKit 中的UIDocumentInteractionControllerQuick Look framework框架。

2.如何预览和打开文档


    任何app都可以使用文档交互控制器进行文件操作。相关交互场景可能发生在需要从网络下载文件进而显示预览的app里。例如,电子邮件类型的app使用文档交互控制器预览或打开某一封邮件附件中的文件。

    除了预览和打开某些文件的需求外,还有一些文件交互是发生在文件共享场景下的。例如,从其他app中通过系统分享或者airdrop分享某些特定类型的文件进行处理。

使用UIDocumentInteractionController进行文件交互


    初始化一个UIDocumentInteractionController实例,并设置代理,由其代理方法可以获知相关视图的信息以及方便在与用户交互时进行一些额外的操作。简单的初始化代码如下:

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

    UIDocumentInteractionController中提供了一些关于文件名、文件类型以及URL的属性,可以方便开发者获取文件相关信息。

UIDocumentInteractionController的两种操作


    UIDocumentInteractionController提供了两种操作文件的方式,一种是文件预览,效果图如下所示:

iOS文档交互(About Document Interaction)_第1张图片
文件预览.png

    预览和打开文件可以使用以下方法:

// 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;

    如果不需要打开文件只是进行文件分享,则可以使用以下方法:

// 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;

    效果图如下:

iOS文档交互(About Document Interaction)_第2张图片
文件分享.png

  demo戳这里查看

3. 打通与其他app之间的文档交互--注册文件支持类型


    上面介绍了app内打开和分享文件的使用,如果你的app支持打开某些特殊类型的文件,并允许其他app通过文件交互技术将文件交给你的app处理的话,你可以在系统注册表中注册相关文件支持类型。

    如果想要声明对某些文件类型的支持,可以在Info.plist中添加CFBundleDocumentTypes键值对。系统会在注册表中添加该信息,然后其他app就可以通过文档交互控制器进行访问了。

    CFBundleDocumentTypes的值是一个字典数组,数组中的每一个字典都包含了一个特定文档类型的相关信息。
    正常情况下文档的类型和这些特定的文件类型是一一对应的,但是如果你的应用程序处理的文件类型不止一个,那么可以将这些文件类型组合在一起,作为单个文档类型来处理。

    例如,如果你的本地文档同时包含一个旧的文件格式和一个新的文件格式,比较典型的像.doc.docx,那么就可以将它们组合在同一个文档类型中。这样,旧的文件格式和新的文件格式就会被当成同一种文档类型,并且使用相同的方式进行处理。

CFBundleDocumentTypes中每个字典都包括以下key:
 - CFBundleTypeName--------------文件类型的名字
 - CFBundleTypeIconFiles---------用于作文件icon的图片名数组
 - LSItemContentTypes------------当前所支持的文件类型的UTI类型的字符串数组
 - LSHandlerRank-----------------标示当前app对该文件类型的权限

    其中LSItemContentTypes中的UTI字符串是真正确定某个文件类型的唯一标示。系统声明的UTI可以点这里查看,非常多

    而LSHandlerRank的权限共分为以下几种:
 - Owner--------------app为该文件类型的主要创建者和拥有者
 - Default------------app为该文件类型的开启者,如果没有指定权限则默认为Default
 - Alternate----------app为该文件类型的二级查看器
 - None---------------app不会被选择打开这个类型的文件,但是它可以接受这种类型的文件

    接收的文件会被存储在app的Document目录的indox文件夹下。

    下面是一个pdf文件类型声明的简单示例:


   CFBundleTypeName
   PDF文件
   CFBundleTypeIconFiles
       
           MySmallIcon.png
           MyLargeIcon.png
       
   LSItemContentTypes
       
           com.adobe.pdf
       
   LSHandlerRank
   Owner

    当app添加文件类型支持之后,用户使用文档交互控制器从其他app分享相关文件类型时,就会发现自己的app在可操作列表里面了。如下图:

iOS文档交互(About Document Interaction)_第3张图片
文件类型支持.png

 当然如果用户是通过airDrop进行文件传输,app同样会出现在可操作列表里面,如下图:

iOS文档交互(About Document Interaction)_第4张图片
airDrop接收列表.png

4. 打开从其他app传过来的文档


    当app添加相关文件类型支持之后,系统可能要求您的应用程序打开一个特定的文件并将其呈现给用户。那么app该如何监听传过来的文件呢?

    这里分两种情况,当app处于未启动状态时,可以通过以下方法获取相关信息:

application:willFinishLaunchingWithOptions:
 或者 
application:didFinishLaunchingWithOptions:

    而文件相关信息包含在上面俩个方法的options参数字典中,你可以通过查看options字典中的以下key来获取相关信息。
 - UIApplicationLaunchOptionsURLKey------------------包含了该文件的NSURL对象
 - UIApplicationLaunchOptionsSourceApplicationKey----包含了文件传输源app的bundleId
 - UIApplicationLaunchOptionsAnnotationKey-----------包含了一个文件传输源app传递过来的关于该文件的属性列表。

    而当app处于启动状态时,则可以通过以下方法获取到传输来的文档相关信息。

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

小贴士:
    如果app只是支持预览某些文件,而不必保存该文件,则可以在以上方法中获取到文件存储到本地的路径,将其删除。

5. Quick Look Framework的使用


    当文件存储到本地之后,为了获得对文件预览的更多控制,可以直接使用 Quick Look Framework

    该框架最主要的类是QLPreviewControllerQLPreviewController提供了代理QLPreviewControllerDelegate响应用户对文件的相关操作,并提供了一个数据源代理QLPreviewControllerDataSource,设置预览文件的相关源数据。

    QLPreviewController可以使用UINavigationControllerpush出来,也可以使用模态的方式弹出。并且使用模态弹出的时候还会有更多操作手势。

    QLPreviewController支持以下文件格式的预览:
 - 苹果自家的iWork相关文档(Pages、Numbers、Keynote)
 - Microsoft办公文档(office97以及之后的版本)
 - PDF文件
 - RTF文档
 - 图片
 - UTI标示符和public.text符合的文本文件
 - csv文件

    QLPreviewController还支持同时预览多个文件,支持多文件的左右切换,由其数据源控制。

6. 小结


    在笔者学习过程中也发现了一些关于UIDocumentInteractionControllerQuick Look framework这些用于进程间通信的remote viewController的限制,比如navtoolbar及其action的无法自定义。

    关于它们的自定义,笔者现在的做法是子类化UIDocumentInteractionControllerQuick Look framework,在控制器的生命周期方法中获取其navtoolbar,修改navtoolbar的相关属性以达到自定义的需求。

    除了以上提到的文档交互相关内容,苹果还提供了
Document Provider Extensions,它允许其他app使用文档选择器来访问文档。
    相关的,开发者也可以在自己的app中集成iCloudKit,进一步加深用户的文档交互操作。(最新出的还有一个PDFKit,这几个有时间笔者会补上ʘʚʘ)

你可能感兴趣的:(iOS文档交互(About Document Interaction))