iOS 从其他App获取文件

作者: 多加辣椒 | 来源:发表于2017-06-19 16:58 被阅读271次

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

    文件共享.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文件添加以下代码:

    <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.plist.png

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

    info.png

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

    share.png

    我们可以看到自己的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

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

    相关文章

      网友评论

        本文标题:iOS 从其他App获取文件

        本文链接:https://www.haomeiwen.com/subject/aeogqxtx.html