iOS 从其他App获取文件

通过UIDocumentInteractionController或者是QLPreviewController来预览PDF等格式文件的时候,我们可以通过自带的UIActivityViewController把该文件共享出去或进行打印等处理。如图所示:

iOS 从其他App获取文件_第1张图片
文件共享.png

第一行的 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的顺序。优先级别从高到低依次是OwnerAlternate,DefaultNone表示不接受这种类型。

我们选择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文件:

iOS 从其他App获取文件_第2张图片
info.plist.png

或者在info页面打开Document types列表:

iOS 从其他App获取文件_第3张图片
info.png

这个时候就代表我们已经成功的注册好了App支持的文件类型,这个时候我们在编译运行,然后再到其他App(我这边用的QQ)打开下载好的文件,这个时候出来的页面是这样的:

iOS 从其他App获取文件_第4张图片
share.png

我们可以看到自己的App图标已经出现在第二栏的列表中,这个时候我们点击图标按钮即可把文件共享到自己App中。

如何处理共享文件

当点击图标按钮的时候,会跳转到我们自己的应用程序中,这个时候在AppDelegate.m会走- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)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 *)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

如果发现本文错误,还请指出!谢谢!!

你可能感兴趣的:(iOS 从其他App获取文件)