1

我正在开发一个基于 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 包装器似乎都会创建资源的一些版本化副本。我不想要版本化的克隆,我只想要具有最新内容的原版文件。

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

4

2 回答 2

2

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

  1. 您似乎不是在包中创建文件,而是在包中创建“包含文件的目录”。那是你打算做的吗?
  2. 似乎如果目录“default”不存在,则创建并使用目录“someFile.ext”,这意味着下次它会创建一个带有奇怪前缀的新目录。但是,我从您的屏幕截图中看到您已经有一个“默认”目录,这意味着这不是您的问题。

现在,您的实际问题:根据此文档addRegularFileWithContents使用您首选的文件名创建一个新文件,除非目录 ( defaultWrapper) 已经包含具有该名称的文件(基本上)。如果已经存在,它会创建一个带有前缀的新文件。 addRegularFileWithContents返回一个引用创建的 NSFileWrapper 的标识字符串(我认为它是文件名)。

所以,发生的事情是,每次你去保存文件时,它都会看到已经有一个同名的文件,并创建一个新的前缀文件。解决此问题的一种方法是保留 NSString 返回的 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 中使用。

在这些更改之后,该程序展示了我认为您所期望的行为:一个目录包含一个文件,即使在多次保存之后也是如此。preservesVersions请注意,即使在返回时也是如此YES。我不确定它存储版本的位置,但我没有看到它们。

于 2014-03-07T21:26:05.207 回答
1

您可以实现 -writeSafely... 以便它直接调用 -writeToURL:... 实现 -writeToURL:... 以便它调用 -fileWrapperOfType:... 然后以原子方式将其写入 URL

即,您将通过让 NSFileWrapper 来接管原子保存的责任。这样,包装器应该巧妙地跟踪文件真正结束的位置。

资源

于 2014-03-09T20:30:04.887 回答