【问题标题】:Why does saving files into a NSDocument create versions of the same file with strange characters in their name?为什么将文件保存到 NSDocument 会创建名称中带有奇怪字符的同一文件的版本?
【发布时间】:2014-02-26 15:34:20
【问题描述】:

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

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

【问题讨论】:

  • + (BOOL)preservesVersions 返回值 YES,如果 NSDocument 的接收子类支持版本;否则否。
  • 好吧,我至少可以确认您列出的额外文件的存在,即使+ (BOOL)preservesVersions 返回 NO 时,无论 + (BOOL)autosavesInPlace 返回什么。更改这两个函数的返回值确实会影响菜单中启用的选项,因此它们正在被查询。如果我发现其他任何东西,我会告诉你的。

标签: appkit nsdocument nsfilewrapper


【解决方案1】:

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

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

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

所以,发生的事情是,每次你去保存文件时,它都会看到已经有一个同名的文件,并创建一个新的前缀文件。解决此问题的一种方法是保留 addRegularFileWithContents 返回的 NSString,然后在保存时检查 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 也是如此。我不确定它存储版本的位置,但我没有看到它们。

【讨论】:

  • 谢谢,正如它在开头所说的那样,“看来您每次都只是添加一个新文件。”是正确的,所以这对我来说是一个相当简单的错误。我认为添加同名文件会覆盖它,但显然不会,所以我必须自己删除重复项。 /“您似乎不是在包中创建文件,而是在包中创建'包含文件的目录'。那是你打算做的吗?” -- 是的。
【解决方案2】:

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

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

Source

【讨论】:

    猜你喜欢
    • 2016-04-13
    • 1970-01-01
    • 2018-03-15
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 2019-03-23
    相关资源
    最近更新 更多