我正在iOS 9.2中创建一个文件/文档提供程序,并使导入和导出操作正常工作.但是,Open操作给我带来了麻烦.
我的文档提供程序将示例文件写入其文件提供程序存储,特别是在以下位置:
/private/var/mobile/Containers/Shared/AppGroup/41EDED34-B449-4FE0-94BA-4046CC573544/File Provider Storage/test.txt
我已经能够从文档提供程序中读取它并验证数据是否正确.但是,当我尝试回读传递给主机应用程序的URL时,我收到权限错误:
Error Domain=NSCocoaErrorDomain Code=257 "The file “test.txt” couldn’t be opened because you don’t have permission to view it." UserInfo={NSFilePath=/private/var/mobile/Containers/Shared/AppGroup/41EDED34-B449-4FE0-94BA-4046CC573544/File Provider Storage/test.txt, NSUnderlyingError=0x15eda7700 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
我使用相当简单的代码进行读写,但如果相关则将其包含在此处:
文件写入:(在我调用dismissGrantingAccessToURL之前在文档提供程序中调用:)
NSString *contents = @"this is a dynamically created text file"; NSLog(@"write to file = %@", fileName); NSError *err; [contents writeToFile:fileName atomically:NO encoding:NSStringEncodingConversionAllowLossy error:&err];
文件读取:(在documentPicker中的主机应用程序内部调用:didPickDocumentAtURL :)
NSString *readback = [[NSString alloc] initWithContentsOfFile:[url path] usedEncoding:nil error:&err];
我从Apple的示例代码开始,并阅读了他们的文档,但没有运气解释为什么这是失败的.
对于我的文件提供程序,只调用init:函数.我不确定这是否正常,或者是否应该为Open操作调用其他方法.这是我的init代码:
- (instancetype)init { self = [super init]; if (self) { [self.fileCoordinator coordinateWritingItemAtURL:[self documentStorageURL] options:0 error:nil byAccessor:^(NSURL *newURL) { // ensure the documentStorageURL actually exists NSError *error = nil; [[NSFileManager defaultManager] createDirectoryAtURL:newURL withIntermediateDirectories:YES attributes:nil error:&error]; }]; } return self; }
我已经验证上面的错误是nil,newURL如下:
file:///private/var/mobile/Containers/Shared/AppGroup/41EDED34-B449-4FE0-94BA-4046CC573544/File%20Provider%20Storage/
更新:我开始明白主机应用无法读取文件的原因.我认为这是因为我在托管应用中没有该应用组的权限.但是,我不认为尝试添加此权限是有意义的,因为主机应用程序应该与支持适当扩展的任何文档提供程序一起使用.
我想我的文件提供程序没有被调用的原因(除了它的初始化:)是因为'open'返回的文件被检测为本地文件,所以不需要复制.要传递本地文件,文档说您必须传递一个位于documentStorageURL内部的URL,然后(按照定义?)将要映射到主机应用程序无法访问的应用程序组.
所以我不确定这将如何运作.如果有人能澄清我应该在这做什么,我会很感激.
在对文档进行了一些深入挖掘之后,我终于找到了问题:在尝试访问它之前,我需要在URL上调用"startAccessingSecurityScopedResource".
请参阅本文档中"访问沙箱外的文件"的"要求"部分:
https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/DocumentPickerProgrammingGuide/AccessingDocuments/AccessingDocuments.html