实现一个简单沙盒文件浏览器(一)

2,905 阅读4分钟

简介

最近接到了一个新的需求,实现一个沙盒文件浏览器。允许用户导入数据,然后再应用里面已列表的形式查看导入沙盒的数据。这里我大致分为两个部分来讲。这一篇是第一节,主要用来讲解沙盒文件的导入,获取,以及类型判断

IMG_0143.jpg

沙盒文件导入

共享沙盒Documents导入数据

注意此功能 需要在iOS11以后的设备上

其原理是将沙盒中的Documents文件夹设置为共享状态,这样我们就可以从外部的文件APP中访问到我们程序的沙盒目录

1.在info中添加两个字段


Supports opening documents in place


Application supports iTunes file sharing

并设置为YES

设置完成之后,我们依旧无法在文件app中查看到。因为里面还没有文件,这时候需要向里面写入一个数据。才能在文件APP中显示我们的应用

这里我们向沙盒的Documents目录中,写入一段文本

- (void) writeString {

    NSString* code = @"sadasdasdad";

    NSData* codeData = [NSData dataWithData:[code dataUsingEncoding:NSUTF8StringEncoding]];

    [codeData writeToFile: sanBoxDocumentPath stringByAppendingPathComponent:@"coder.txt"] atomically:NO];

}

写入完毕之后我们可以看到在文件APP下,我的iphone目录中,出现了一个当前程序的沙盒文件目录,这里对应的沙盒目录就是我们程序中沙盒目录的Documents目录。

IMG_4F4216744E54-1.jpeg

这样一来我们就可以将相册中的照片,或者其他的文件(PDF,MOV,MP3等等),通过这个共享的沙盒目录导入。方便我们的调试

获取沙盒文件

通过调用NSFileManager的contentsOfDirectoryAtPath方法,我们可以搜索到当前目录下的Item(有文件也有文件夹),注意这是一个浅搜索(不会对当前目录下的文件夹进行递归) 返回的是一个文件名组成的数组

folder1
IMG_5902.HEIC
coder.txt
.trash

从数组结构上看,我们发现里面没有后缀的都是文件夹,有后缀的都是类型文件

但是这里我们发现这些文件只有名称没有,文件元数据(例如文件创建时间,文件大小等等)

因此我们还需要调用attributesOfItemAtPath来获取文件的元数据

沙盒文件类型判断

iOS UTI(Universal Type Identifier)

同一类型标识符(Uniform Type Identifier,UTI)代表IOS信息共享的中心组件。可以把它看成下一代的MIME类型。UTI是标识资源类型(比如图像和文本)的字符串,他们制定哪些类型的信息将用于公共数据对象,他们不需要依赖于老式的指示符,比如文件扩展名,MIME类型,或者文件类型的元数据

image.png

如上图所示例子

将png类型图片统一成public.png 依次方式处理jpeg gif 等多种类型图片
下一步在public.png 和 public.jpeg ,public.gif 统一用public.image类型表示,所有类型的图片 同理可得文字类型public.text 其包含的类型有.txt .xml .rtf等等文字类型的数据 public.text和public.image都代表数据类型,所以也可以统一成public.data 而public.item代表了数据类型和目录类型,包含了public.data 和 public.directory

这样我们就可以从一堆文件中快速找到图片类型获取其他类型的文件,而不必根据后缀名一个一个的判断

完整的关系对应图,可以参照苹果官方提供的对照表

苹果官网UTI类型

image.png

image.png

第一行代表当前类型
第二行代表当前类型所属的上一级类型
第三行代表其文件的拓展格式
第四行代表苹果对该类型文件的解释

使用UTI类型来判断沙盒文件类型

可以通过CoreFoundation框架提供的方法来根据文件的沙盒路径来判断其类型。

extern Boolean 
UTTypeConformsTo(
  CFStringRef   inUTI,
  CFStringRef   inConformsToUTI
 )                                     

首先我们将需要判断的文件的沙盒路径传入,判断其是否有后缀如果有后缀就代表是目录类型


- (CFStringRef) getFileUTType:(NSString*) path {

    NSString* fileExt = path.pathExtension;
    if(fileExt.isEmpty){
        BOOL isDirectory;
        if ([[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:&isDirectory]) {
            if (isDirectory) {
                return kUTTypeFolder;
            }
        }
    }
    CFStringRef cfFileExt = (__bridge CFStringRef)fileExt;
    CFStringRef utType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,cfFileExt, nil);

    return utType;

}

在获取UTI类型之后使用方法UTTypeConformsTo来判断类型是否是指定类型。

UTTypeConformsTo(utType, kUTTypeImage)