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 <UIDocumentInteractionControllerDelegate>) interactionDelegate {
 
     UIDocumentInteractionController *interactionController =
        [UIDocumentInteractionController interactionControllerWithURL: fileURL];
     interactionController.delegate = interactionDelegate;
 
     return interactionController;
 }

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

UIDocumentInteractionController的两种操作


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

文件预览.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;

    效果图如下:

文件分享.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文件类型声明的简单示例:

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

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

文件类型支持.png

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

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,这几个有时间笔者会补上ʘʚʘ)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容