最近在做一个文档管理的个人项目时碰到了一些关于这样那样的iOS文档交互处理的问题,在这里做一个小结😊
目录:
- iOS中的文档交互简介
- 如何预览和打开文档
- 打通与其他app之间的文档交互--注册文件支持类型
- 打开从其他app传过来的文档
- Quick Look Framework的使用
- 小结
1.iOS中的文档交互简介
iOS中为开发者提供了一种即便app并不支持某些文件,也可以打开预览该文件的技术。
iOS中还提供了一个关联文件类型的系统注册表,如果你的app注册了相关文件的类型,那么系统会允许你的app可以处理从其他应用程序中打开的文件;同时支持处理airDrop传输过来的文件。
这些强大的技术包括 UIKit
中的UIDocumentInteractionController
和 Quick 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
提供了两种操作文件的方式,一种是文件预览,效果图如下所示:
预览和打开文件可以使用以下方法:
// 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;
效果图如下:
文件分享.pngdemo戳这里查看
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接收列表.png4. 打开从其他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
。
该框架最主要的类是QLPreviewController
,QLPreviewController
提供了代理QLPreviewControllerDelegate
响应用户对文件的相关操作,并提供了一个数据源代理QLPreviewControllerDataSource
,设置预览文件的相关源数据。
QLPreviewController
可以使用UINavigationController
push出来,也可以使用模态的方式弹出。并且使用模态弹出的时候还会有更多操作手势。
QLPreviewController
支持以下文件格式的预览:
- 苹果自家的iWork相关文档(Pages、Numbers、Keynote)
- Microsoft办公文档(office97以及之后的版本)
- PDF文件
- RTF文档
- 图片
- UTI标示符和public.text
符合的文本文件
- csv文件
QLPreviewController
还支持同时预览多个文件,支持多文件的左右切换,由其数据源控制。
6. 小结
在笔者学习过程中也发现了一些关于UIDocumentInteractionController
和 Quick Look framework
这些用于进程间通信的remote viewController的限制,比如nav
和toolbar
及其action的无法自定义。
关于它们的自定义,笔者现在的做法是子类化UIDocumentInteractionController
和 Quick Look framework
,在控制器的生命周期方法中获取其nav
和toolbar
,修改nav
和toolbar
的相关属性以达到自定义的需求。
除了以上提到的文档交互相关内容,苹果还提供了
Document Provider Extensions,它允许其他app使用文档选择器来访问文档。
相关的,开发者也可以在自己的app中集成iCloudKit
,进一步加深用户的文档交互操作。(最新出的还有一个PDFKit,这几个有时间笔者会补上ʘʚʘ)
网友评论