iOS 打开系统文件APP,从文件中读取

  • Post author:
  • Post category:其他


公司是做文件工具类的 App,因此在 Apple 发布新的 iOS 11 后,我司加入了需求,需要允许 App 沙盒内的文件使用 Files 管理,现找到的资料不多,除了苹果的官方文档外,

这篇

是一个简单入门的博客来了解如何接入 Files。

让你的 App 出现在 Files 里面

在你的 App 内的文件可以出现在 Files 里面之前,你必须保证你的 App 是支持 Files 中打开并且可以分享的。这需要你在你的 App 内的 Info.plist 中添加两个键值对,第一个是 UIFileSharingEnabled,这个可以使 iTunes 分享你文件夹内的内容;第二个是 LSSupportsOpeningDocumentsInPlace ,它保证了你文件夹内本地文件的获取权限,你需要将这两个键值对的值设置为 YES ,如下:

然后你再次运行你的程序,就可以在 Files 里面

我的 iPhone

中看到以你项目名为文件夹名的文件夹(如果你在 Files 中看不到

我的 iPhone

这一项,你只需要在照片中选中一张照片共享到 Files 里面,就可以看到这一项了)

Files 里面的文件

在 Files 里面的文件夹,会将沙盒内 Documents 文件夹内的所有文件都显示出来,因此苹果建议在此文件夹中只存放用户创建的文件,如果将 App 创建的文件也放到这个目录下的话,会使这个文件夹看起来很杂乱。

如何隐藏重要的文件

我们应该如何存储 App 创建的文件呢?这个取决于它的重要性,如果它不是那么重要的,我们可以将它们存放在 cachesDirectory 或者是 temporaryDirectory 文件夹下面;如果它是重要的文件,大多数情况下,我们是需要将它们备份在 iCloud 上的,这样的文件我们建议将它存放在 applicationSupportDirectory 目录下,如下:

// let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let support = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!

Application Support directory 文件夹内的内容可以备份在 iCloud 上,同时不会出现在 Files App 内。

这个是简单的将你 App 内的文件在 Files 中展示出来,具体点击了某个文件之后的操作,是需要在 App 内

BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *)options

方法中根据产品经理的需求去实现的。

另一种方法

这是一种简单的接入 Files 的方法,此时你的所有文件都是在

我的 iPhone

里面的文件夹中展示,还有一种是与

我的 iPhone

同级的展示,如下图:

如果想要像 OneDrive 或者是 DropBox 这样的 App 一样直接打开 Files 就可以看到你们的 App ,这就需要我们在自己的 App 中添加 FileProviderExtension ,这样就可以实现上面这样的需求,具体怎么操作,还需要在看其他的文章了 , 这里只是一个引子(其实是我们没这个需求)。


https://www.jianshu.com/p/61b4e26ab413

最近公司项目要求在IM会话页面添加发送文件的功能,然后就研究了下。

IM一般的SDK都会有发送文件的功能,但是在选择文件的时候就遇到了问题

文件从哪里来?

1.由于iOS 系统沙盒的限制,你是不能像安卓手机那样直接查看手机所有文件的,也就是说,你只能操作当前应用内部的文件。


iOS文件管理参考1



iOS文件管理参考2


2.像微信那样从iCloud中拿,也可以理解为苹果的原生应用Files里拿的,这些都是互通的


我参考了这个

iCloud初步了解(应该很片面)


苹果在iOS11之后感觉是打开了文件管理这方面的限制,但其实还是没有做到,因为你还是不能跨应用访问。通过iCloud 访问也只不多时苹果为了推广他的云同步罢了。


即使在iCloud 里能访问到A应用里的文件,那也要A应用打开iCloud,并做了写入文件到iCloud目录下这件事

重点来了,据我目前不全面的了解,国内还是很少有人用iCloud的,首先一个Apple ID就5G的云存储空间,要想真的用起来,就要花钱买(6块钱一个月50G),毕竟现在随便存点东西就5G了吧。

如果你仅仅只有一个iPhone的话,iCloud其实没啥用,就存手机里就好了;但是你要是有多个Apple 设备,或者是苹果全家桶的话,其实还是很有用的,毕竟一个账号就能让你所有的设备都有这相同的配置和使用习惯,还是很方便的。

发送文件

知道这些之后,我就开始着手发送文件了

1.

UIDocumentPickerViewController

见名知意

    NSArray *documentTypes = @[@"public.text",
                               @"public.content",
                               @"public.source-code",
                               @"public.image",
                               @"public.audiovisual-content",
                               @"com.adobe.pdf",
                               @"com.apple.keynote.key",
                               @"com.microsoft.word.doc",
                               @"com.microsoft.excel.xls",
                               @"com.microsoft.powerpoint.ppt"];
    
    UIDocumentPickerViewController *documentPickerViewController = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:documentTypes inMode:UIDocumentPickerModeImport];
    documentPickerViewController.delegate = self;
    [self presentViewController:documentPickerViewController animated:YES completion:nil];


2.实现代理

- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url {

    BOOL fileUrlAuthozied = [url startAccessingSecurityScopedResource];
    if (fileUrlAuthozied && [self iCloudEnable]) {
        //通过文件协调工具来得到新的文件地址,以此得到文件保护功能
        NSFileCoordinator *fileCoordinator = [[NSFileCoordinator alloc] init];
        NSError *error;
        
        [fileCoordinator coordinateReadingItemAtURL:url options:0 error:&error byAccessor:^(NSURL *newURL) {
            //读取文件
            NSString *fileName = [newURL lastPathComponent];
            fileName = [fileName stringByRemovingPercentEncoding];
            
            [self downloadWithDocumentURL:newURL callBack:^(id obj) {
                NSData *data = obj;
                if (data) {
                    NSString *path = [GDSandboxFile getDirectoryForDocuments:[NSString stringWithFormat:@"SendFiles"]];
                    NSString *pathStr = [path stringByAppendingPathComponent:fileName];
                    if (![[NSFileManager defaultManager] fileExistsAtPath:pathStr]) {
                        [data writeToFile:pathStr atomically:YES];
                    }
                    //上传
                    RCFileMessage *content = [RCFileMessage messageWithFile:pathStr];
                    [self sendMessage:content pushContent:LS(@"文件")];
                    
                }
                
            }];
            
            [self dismissViewControllerAnimated:YES completion:NULL];
        }];
        [url stopAccessingSecurityScopedResource];
    }
}

其中

downloadWithDocumentURL

方法是和同事一起讨论后得出的解决办法,因为得到的这个

NSURL *newURL

在我发送文件的时候就是个无效的路径,后来就想到在路劲可用的时候存到自己的沙盒下,然后在拿来用。这样其他地方也能用这个文件了,不用每次都去iCloud下面取。

    
    UIDocument *iCloudDoc = [[UIDocument alloc]initWithFileURL:url];
    
    [iCloudDoc openWithCompletionHandler:^(BOOL success) {
        if (success) {
            
            [iCloudDoc closeWithCompletionHandler:^(BOOL success) {
                NSLog(@"关闭成功");
            }];
            
            if (block) {
                block(iCloudDoc.data);
            }
        }
    }];
}

这样就达到了我们想要的效果


链接:https://www.jianshu.com/p/5704230a2743