通过UIDocumentInteractionController
或者是QLPreviewController
来预览PDF等格式文件的时候,我们可以通过自带的UIActivityViewController
把该文件共享出去或进行打印等处理。如图所示:
第一行的
AirDrop
是iOS7之后给用户提供的一种在苹果设备之间共享文件的快捷方式,类似于安卓上的蓝牙无线传输文件。
第二行是通过文档类型关联技术识别的App的列表。
第三行是通过文档关联技术识别的Action
的列表,表示对文件可进行的一些操作,如复制,打印,保存等。
我们知道在iOS系统下有一种安全体系--沙盒机制
,每个iOS应用程序都是一个独立的文件系统,并且只能在自己的文件系统进行操作,所以iOS系统下并不能像安卓一样轻松取到其他应用程序下的文件。
既然我们能在自己的应用程序下预览文件时把文件共享到其他App中,那么反过来怎么能让其他App共享文件到我们App呢?
info.plist注册文件类型
我们需要在info.plist
文件中,添加一个新的属性CFBundleDocumentTypes
(实际上输入的是Document type
),这是一个数组类型的属性,意思就是我们可以同时注册多个类型。而针对数组中的每一个元素,都有许多属性可以指定,详细的属性列表我们可以从官方文档上找到: Core Foundation Keys ---- CFBundleDocumentTypes。这里列举我们在做iOS开发时常用的属性:
-
CFBundleTypeName
字符串类型,指定某种类型的别名,也就是用来指代我们规定的类型的别称,一般为了保持唯一性,我们使用UTI来标识。
CFBundleTypeIconFiles
数组类型,包含指定的png图标的文件名,指定代表某种类型的图标,而图标有具体的尺寸标识:
Device | Sizes |
---|---|
iPad | 64 x 64 pixels, 320 x 320 pixels |
iPhone and iPod touch | 22 x 29 pixels, 44 x 58 pixels (high resolution) |
- LSItemContentTypes
数组类型,包含UTI字符串,指定我们的应用程序所有可以识别的文件类型集合
- LSHandlerRank
字符串类型,包含Owner
,Default
,Alternate
,None
四个可选值,指定对于某种类型的优先权级别,而Launcher Service
会根据这个优先级别来排列显示的App的顺序。优先级别从高到低依次是Owner
,Alternate
,Default
。None
表示不接受这种类型。
我们选择Source code
方式打开info.plist
文件添加以下代码:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeName</key>
<string>PDF</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.adobe.pdf</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Microsoft Word</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.microsoft.word.doc</string>
<string>com.microsoft.word.wordml</string>
<string>org.openxmlformats.wordprocessingml.document</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Microsoft Excel</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.microsoft.excel.xls</string>
<string>org.openxmlformats.spreadsheetml.sheet</string>
</array>
</dict>
<dict>
<key>CFBundleTypeIconFiles</key>
<array/>
<key>CFBundleTypeName</key>
<string>Microsoft PowerPoint</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.microsoft.powerpoint.ppt</string>
<string>org.openxmlformats.presentationml.presentation</string>
<string>public.presentation</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Text</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.text</string>
<string>public.plain-text</string>
<string>public.utf8-plain-text</string>
<string>public.utf16-external-plain-text</string>
<string>public.utf16-plain-text</string>
<string>com.apple.traditional-mac-plain-text</string>
<string>public.source-code</string>
<string>public.c-source</string>
<string>public.objective-c-source</string>
<string>public.c-plus-plus-source</string>
<string>public.objective-c-plus-plus-source</string>
<string>public.c-header</string>
<string>public.c-plus-plus-header</string>
<string>com.sun.java-source</string>
<string>public.script</string>
<string>public.shell-script</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Rich Text</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.rtf</string>
<string>com.apple.rtfd</string>
<string>com.apple.flat-rtfd</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>HTML</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.html</string>
<string>public.xhtml</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Web Archive</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.webarchive</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Image</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.image</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>iWork Pages</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.page.pages</string>
<string>com.apple.iwork.pages.pages</string>
<string>com.apple.iwork.pages.template</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>iWork Numbers</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.numbers.numbers</string>
<string>com.apple.iwork.numbers.numbers</string>
<string>com.apple.iwork.numbers.template</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>iWork Keynote</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>com.apple.keynote.key</string>
<string>com.apple.iwork.keynote.key</string>
<string>com.apple.iwork.keynote.kth</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Audio</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.audio</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Movie</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.movie</string>
</array>
</dict>
<dict>
<key>CFBundleTypeName</key>
<string>Archive</string>
<key>LSHandlerRank</key>
<string>Alternate</string>
<key>LSItemContentTypes</key>
<array>
<string>public.archive</string>
</array>
</dict>
</array>
添加这些代码,你的App就可以支持大部分文件类型了,可以根据自己项目的需求,添加相关类型的代码,像我自己的项目只需要支持PDF和word格式的文件。添加完这些代码,我们选择Property list
打开info.plist文件:
或者在info
页面打开Document types
列表:
这个时候就代表我们已经成功的注册好了App支持的文件类型,这个时候我们在编译运行,然后再到其他App(我这边用的QQ)打开下载好的文件,这个时候出来的页面是这样的:
我们可以看到自己的App图标已经出现在第二栏的列表中,这个时候我们点击图标按钮即可把文件共享到自己App中。
如何处理共享文件
当点击图标按钮的时候,会跳转到我们自己的应用程序中,这个时候在AppDelegate.m
会走- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
该回调方法。
但是在iOS9之前回调的是- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation
,所以我们需要针对不同的设备版本做出改变。
我们可以在回调方法里进行文件处理操作,如将文件上传、文件预览、文件保存一些工作。在做文件预览的时候我们必定得跳转到对应的控制器中,这个时候我们首先得获取到当前的视图控制器
//获取当前屏幕显示的viewcontroller
- (UIViewController *)getCurrentVC
{
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *currentVC = [self getCurrentVCFrom:rootViewController];
return currentVC;
}
- (UIViewController *)getCurrentVCFrom:(UIViewController *)rootVC
{
UIViewController *currentVC;
if ([rootVC presentedViewController]) {
// 视图是被presented出来的
rootVC = [rootVC presentedViewController];
}
if ([rootVC isKindOfClass:[UITabBarController class]]) {
// 根视图为UITabBarController
currentVC = [self getCurrentVCFrom:[(UITabBarController *)rootVC selectedViewController]];
} else if ([rootVC isKindOfClass:[UINavigationController class]]){
// 根视图为UINavigationController
currentVC = [self getCurrentVCFrom:[(UINavigationController *)rootVC visibleViewController]];
} else {
// 根视图为非导航类
currentVC = rootVC;
}
return currentVC;
}
拿到控制器我们可以回到回调方法里进行跳转工作,我这边还是用UIDocumentInteractionController
做文件预览
#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_9_0
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(nullable NSString *)sourceApplication annotation:(id)annotation{
// 判断传过来的url是否为文件类型
if ([url.scheme isEqualToString:@"file"]) {
_docVc = [UIDocumentInteractionController interactionControllerWithURL:url];
_docVc.delegate = self;
[_docVc presentPreviewAnimated:YES];
}
}
#else
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options{
// 判断传过来的url是否为文件类型
if ([url.scheme isEqualToString:@"file"]) {
_docVc = [UIDocumentInteractionController interactionControllerWithURL:url];
_docVc.delegate = self;
[_docVc presentPreviewAnimated:YES];
}
return YES;
}
#endif
#pragma mark -- UIDocumentInteractionControllerDelegate
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
// 返回当前控制器
return [self getCurrentVC];
}
参考文章 :详解苹果提供的UTI(统一类型标识符)
本文Demo示例:WYShareFile
如果发现本文错误,还请指出!谢谢!!