我使用NSFileWrapper作为我的包文档。有时,当我请求包内文件的数据时,就会得到nil。
以下是我如何查询包内文件的数据:
- (NSData*) dataOfFile(NSString*)filename {
NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
return fileWrapper.regularFileContents; // This returns nil sometimes. Why?
}此方法最终开始对某些文件(并非全部)返回零。不幸的是,我没有成功地重复这个问题。
如果有用的话,我就是这样打开包的:
- (BOOL) readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
self.documentFileWrapper = fileWrapper;
return YES;
}以下是我如何更新包内文件的数据:
- (void) updateFile:(NSString*)filename withData:(NSData*)data {
SBFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
if (fileWrapper) {
[self.documentFileWrapper removeFileWrapper:fileWrapper];
}
NSFileWrapper *fileWrapper = [[SBFileWrapper alloc] initRegularFileWithContents:data ];
fileWrapper.preferredFilename = filename;
[self.documentFileWrapper addFileWrapper:fileWrapper];
}我就是这样保存包的:
- (NSFileWrapper*) fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
return self.documentFileWrapper;
}为什么会发生这种事?有什么办法可以防止吗?
regularFileContents的文档似乎谈到了这个问题:
如果用户在调用readFromURL:options:error:或initWithURL:options:error:但在NSFileWrapper读取文件内容之前修改文件,则此方法可能返回零。使用NSFileWrapperReadingImmediate读取选项可以减少出现该问题的可能性。
但是,我不明白为了防止这种情况,必须在上面的代码中更改什么。
失败的实验
如果regularFileContents返回零,我试着保存文档,但之后它仍然返回零。如下所示:
- (NSData*) dataOfFile(NSString*)filename {
NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
NSData *data = fileWrapper.regularFileContents;
if (!data) {
[self saveDocument:nil];
fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
data = fileWrapper.regularFileContents;
}
return data;
}发布于 2013-02-03 02:24:38
没有足够的代码来查看到底发生了什么。然而,根本原因是NSFileWrapper正是其名称所暗示的:一个表示文件或目录的对象。因此,实际的文件或目录可以很容易地与驻留在内存中的对象“脱离同步”。每当NSFileWrapper确定已经发生这种情况时,它就会对某些操作返回零。解决方案是使NSFileWrapper对象短暂存在。在需要时创建并打开它们,然后尽快保存和关闭它们。
特别是,您的代码似乎在很长一段时间内一直保持指向包目录包装器的指针,并假定它始终有效。如果目录因任何原因发生变化,则情况并非如此。这样,每次需要时,您都会得到一个新的包目录包装器,这个问题就应该解决了。
发布于 2013-02-05 04:31:11
如果文件在磁盘上更改,那么您将得到零(如@Gene所述)。但是,您可以使用matchesContentsOfURL:方法检查这一点,该方法如下:
根据上次读取或写入文件时存储的文件属性,确定磁盘表示形式是否已更改。如果文件包装器的修改时间或访问权限与磁盘上文件的修改时间或访问权限不同,则此方法返回“是”。然后您可以使用
readFromURL:options:error:
这是来自使用文件包装器苹果公司的文档。
请注意,在该节的介绍中:
因为文件包装器的目的是表示内存中的文件,所以它非常松散地耦合到任何磁盘表示。文件包装器不会记录到其内容的磁盘表示形式的路径。这允许您使用不同的URL保存相同的文件包装,但如果以后要从磁盘更新文件包装,则还需要记录这些URL。
因此,如果您想要/需要重新读取它,您必须将url保存到原始文件。
当您看到零结果时,了解matchesContentsofURL:返回的内容很有趣。
https://stackoverflow.com/questions/12911438
复制相似问题