为什么将文件保存到 NSDocument 中会创建名称中带有奇怪字符的同一文件的版本?

StackOverflow https://stackoverflow.com//questions/22046035

我正在开发一个基于 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”与一些内容保存到其中。

现在,问题来了。当我查看磁盘上实际保存的内容时,我看到:

screenshot

每次我保存文件时, NSDocument 包装器似乎都会创建资源的一些版本副本。我不需要版本控制的克隆,我只想要包含最新内容的普通文件。

版本化资源从哪里来?这里发生了什么?有我应该阅读的文档吗?

有帮助吗?

解决方案

好吧,我想我明白了。事实证明,这实际上不是版本控制问题。看来您每次只是添加一个新文件。首先,一些注意事项。

  1. 您似乎不是在包中创建文件,而是在包中创建“包含文件的目录”。这就是你打算做的吗?
  2. 看来,如果目录“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;
}
  1. 我已经改变了 defaultWrapper的首选文件名是“默认”,正如我怀疑你的意图。
  2. 我添加了一个 if 删除先前保存的文件(如果存在)的块。
  3. 我已经让它存储了新的 NSFileWrapper 的文件名,以供下次在 #2 中使用。

经过这些更改后,该程序演示了我认为您期望的行为:一个目录包含一个文件,即使保存多次后也是如此。请注意,即使当 preservesVersionsYES. 。我不确定它的版本存储在哪里,但我没有看到它们。

其他提示

你可以实现 - 遍布......所以它直接呼叫 - 犯罪:...... 实现-writetourl:......所以它调用-filewrapperoftype:......然后将其写入URL 原子/ em>

i.e。通过使NSFileWrapper做到这一点,您将接管原子豁免的责任。这种方式,包装器应该整齐地追踪文件真正最终的位置。

source

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top