为什么将文件保存到 NSDocument 中会创建名称中带有奇怪字符的同一文件的版本?
-
21-12-2019 - |
题
我正在开发一个基于 NSDocument 的应用程序,其文档类型是包含一堆文件的包。我这样保存它:
- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError
{
if (!self.documentFileWrapper) {
NSFileWrapper *documentFileWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
[self setDocumentFileWrapper:documentFileWrapper];
}
NSFileWrapper *defaultWrapper = [self.documentFileWrapper.fileWrappers objectForKey:@"default"];
if (!defaultWrapper) {
defaultWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
[defaultWrapper setPreferredFilename:@"someFile.ext"];
[self.documentFileWrapper addFileWrapper:defaultWrapper];
}
[defaultWrapper addRegularFileWithContents: ... some computed content for the file ... preferredFilename:@"someFile.ext"];
return self.documentFileWrapper;
}
换句话说,在捆绑包中创建一个文件夹“default”,并将“someFile.ext”与一些内容保存到其中。
现在,问题来了。当我查看磁盘上实际保存的内容时,我看到:
每次我保存文件时, NSDocument 包装器似乎都会创建资源的一些版本副本。我不需要版本控制的克隆,我只想要包含最新内容的普通文件。
版本化资源从哪里来?这里发生了什么?有我应该阅读的文档吗?
解决方案
好吧,我想我明白了。事实证明,这实际上不是版本控制问题。看来您每次只是添加一个新文件。首先,一些注意事项。
- 您似乎不是在包中创建文件,而是在包中创建“包含文件的目录”。这就是你打算做的吗?
- 看来,如果目录“default”不存在,您将创建并使用目录“someFile.ext”,这意味着下次它会创建一个带有奇怪前缀的新目录。但是,我从您的屏幕截图中看到您已经有一个“默认”目录,这意味着这不是您的问题。
现在,你的实际问题:根据 本文档, addRegularFileWithContents
使用您首选的文件名创建一个新文件, 除非 目录(defaultWrapper
)已经包含一个具有该名称的文件(基本上)。如果已经存在,它将创建一个带有前缀的新文件。 addRegularFileWithContents
返回一个引用创建的 NSFileWrapper 的标识字符串(我认为它是文件名)。
因此,发生的情况是,每次您去保存文件时,它都会看到已经有一个同名的文件,并创建一个新的前缀文件。解决这个问题的一种方法是保留返回的 NSString addRegularFileWithContents
, ,然后当你去保存时检查 defaultWrapper
并删除与存储的 NSString 关联的 NSFileWrapper(如果有),然后像平常一样添加文件。我已将您的代码修改如下:
@interface TestDocument () // Relevant part of my test class. Note `wrapperFileName`.
@property (nonatomic, strong) NSFileWrapper *documentFileWrapper;
@property (nonatomic, strong) NSString *wrapperFileName;
@end
- (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError
{
if (!self.documentFileWrapper) {
NSFileWrapper *documentFileWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
[self setDocumentFileWrapper:documentFileWrapper];
}
NSFileWrapper *defaultWrapper = [self.documentFileWrapper.fileWrappers objectForKey:@"default"];
if (!defaultWrapper) {
defaultWrapper = [[NSFileWrapper alloc] initDirectoryWithFileWrappers:nil];
[defaultWrapper setPreferredFilename:@"default"];
[self.documentFileWrapper addFileWrapper:defaultWrapper];
} else if (self.wrapperFileName) {
[defaultWrapper removeFileWrapper:[[defaultWrapper fileWrappers] objectForKey:self.wrapperFileName]];
}
self.wrapperFileName = [defaultWrapper addRegularFileWithContents:[@"blah blah" dataUsingEncoding:NSUTF8StringEncoding] preferredFilename:@"someFile.txt"];
return self.documentFileWrapper;
}
- 我已经改变了
defaultWrapper
的首选文件名是“默认”,正如我怀疑你的意图。 - 我添加了一个
if
删除先前保存的文件(如果存在)的块。 - 我已经让它存储了新的 NSFileWrapper 的文件名,以供下次在 #2 中使用。
经过这些更改后,该程序演示了我认为您期望的行为:一个目录包含一个文件,即使保存多次后也是如此。请注意,即使当 preservesVersions
回 YES
. 。我不确定它的版本存储在哪里,但我没有看到它们。
其他提示
你可以实现 - 遍布......所以它直接呼叫 - 犯罪:...... 实现-writetourl:......所以它调用-filewrapperoftype:......然后将其写入URL 原子/ em>
i.e。通过使NSFileWrapper做到这一点,您将接管原子豁免的责任。这种方式,包装器应该整齐地追踪文件真正最终的位置。