通过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
文件添加以下代码:
CFBundleDocumentTypes
CFBundleTypeName
PDF
LSHandlerRank
Owner
LSItemContentTypes
com.adobe.pdf
CFBundleTypeName
Microsoft Word
LSHandlerRank
Alternate
LSItemContentTypes
com.microsoft.word.doc
com.microsoft.word.wordml
org.openxmlformats.wordprocessingml.document
CFBundleTypeName
Microsoft Excel
LSHandlerRank
Alternate
LSItemContentTypes
com.microsoft.excel.xls
org.openxmlformats.spreadsheetml.sheet
CFBundleTypeIconFiles
CFBundleTypeName
Microsoft PowerPoint
LSHandlerRank
Alternate
LSItemContentTypes
com.microsoft.powerpoint.ppt
org.openxmlformats.presentationml.presentation
public.presentation
CFBundleTypeName
Text
LSHandlerRank
Alternate
LSItemContentTypes
public.text
public.plain-text
public.utf8-plain-text
public.utf16-external-plain-text
public.utf16-plain-text
com.apple.traditional-mac-plain-text
public.source-code
public.c-source
public.objective-c-source
public.c-plus-plus-source
public.objective-c-plus-plus-source
public.c-header
public.c-plus-plus-header
com.sun.java-source
public.script
public.shell-script
CFBundleTypeName
Rich Text
LSHandlerRank
Alternate
LSItemContentTypes
public.rtf
com.apple.rtfd
com.apple.flat-rtfd
CFBundleTypeName
HTML
LSHandlerRank
Alternate
LSItemContentTypes
public.html
public.xhtml
CFBundleTypeName
Web Archive
LSHandlerRank
Alternate
LSItemContentTypes
com.apple.webarchive
CFBundleTypeName
Image
LSHandlerRank
Alternate
LSItemContentTypes
public.image
CFBundleTypeName
iWork Pages
LSHandlerRank
Alternate
LSItemContentTypes
com.apple.page.pages
com.apple.iwork.pages.pages
com.apple.iwork.pages.template
CFBundleTypeName
iWork Numbers
LSHandlerRank
Alternate
LSItemContentTypes
com.apple.numbers.numbers
com.apple.iwork.numbers.numbers
com.apple.iwork.numbers.template
CFBundleTypeName
iWork Keynote
LSHandlerRank
Alternate
LSItemContentTypes
com.apple.keynote.key
com.apple.iwork.keynote.key
com.apple.iwork.keynote.kth
CFBundleTypeName
Audio
LSHandlerRank
Alternate
LSItemContentTypes
public.audio
CFBundleTypeName
Movie
LSHandlerRank
Alternate
LSItemContentTypes
public.movie
CFBundleTypeName
Archive
LSHandlerRank
Alternate
LSItemContentTypes
public.archive
添加这些代码,你的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
该回调方法。
但是在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 *)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
如果发现本文错误,还请指出!谢谢!!