公司是做文件工具类的 App,因此在 Apple 发布新的 iOS 11 后,我司加入了需求,需要允许 App 沙盒内的文件使用 Files 管理,现找到的资料不多,除了苹果的官方文档外,这篇是一个简单入门的博客来了解如何接入 Files。
在你的 App 内的文件可以出现在 Files 里面之前,你必须保证你的 App 是支持 Files 中打开并且可以分享的。这需要你在你的 App 内的 Info.plist 中添加两个键值对,第一个是 UIFileSharingEnabled,这个可以使 iTunes 分享你文件夹内的内容;第二个是 LSSupportsOpeningDocumentsInPlace ,它保证了你文件夹内本地文件的获取权限,你需要将这两个键值对的值设置为 YES ,如下:
然后你再次运行你的程序,就可以在 Files 里面 我的 iPhone 中看到以你项目名为文件夹名的文件夹(如果你在 Files 中看不到 我的 iPhone 这一项,你只需要在照片中选中一张照片共享到 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
方法中根据产品经理的需求去实现的。
这是一种简单的接入 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里拿的,这些都是互通的
我参考了这个
苹果在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