在(以编程方式)重命名NSDocument文件时阻止警告

d11*_*wtq 5 macos cocoa objective-c nsdocument

我的应用程序允许用户重命名当前打开的文档.这是微不足道的,并且工作正常,有一个我无法弄清楚的非常烦人的错误.重命名文件时,AppKit(善意)会在下次尝试保存文档时向用户发出警告.用户说"OK",一切都正常.当应用程序外部的某些内容更改了文档时,这是有道理的,而不是在文档本身实际完成时.

代码如下:

-(void)renameDocumentTo:(NSString *)newName {
  NSURL *newURL = [[[self fileURL] URLByDeletingLastPathComponent]
                                   URLByAppendingPathComponent:newName];

  NSFileManager *fileManager = [NSFileManager defaultManager];
  [fileManager moveItemAtURL:[self fileURL] toURL:newURL];
  NSDictionary *attrs = [fileManager attributesForItemAtPath:[newURL path] error:NULL];

  [self setFileURL:newURL];
  [self setFileModificationDate:[attrs fileModificationDate]];
}
Run Code Online (Sandbox Code Playgroud)

有人会认为在文档上明确设置新的URL和修改日期就足够了,但遗憾的是它不是.Cocoa仍会生成警告.

我已经尝试更改顺序(在文档上设置新URL,然后重命名文件),但这没有帮助.

我也尝试过用户在CocoaDev的旧帖子上建议修复:

[self performSelector:@selector(_resetMoveAndRenameSensing)];
Run Code Online (Sandbox Code Playgroud)

即使这样也不会停止警告,我猜测必须有一个正确的方法来使用记录的API来做到这一点.当用户单击项目树上的文件并将其重命名为其他内容时,Xcode如何处理事物.它不会警告用户重命名,因为用户实际执行了重命名.

如果有人能够对我可能需要做的事情有所了解,那就太棒了,谢谢!

Mik*_*lah 3

主要文档中对此没有太多内容。相反,请查看 10.5 发行说明:http://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKitOlderNotes.html%23X10_5Notes,标题为“NSDocument Checking for Modified Files At Saving Time”

(对于 Xcode,它有着悠久的历史,如果 if 不用于NSDocument项目内的文件,我不会感到惊讶)

值得注意的是,移动文件不会更改其修改日期,因此调用-setFileModificationDate:不太可能产生任何效果。

因此一种可能是绕过NSDocument通常的警告,如下所示:

- (void)saveDocument:(id)sender;
{
    if (wasRenamed)
    {
        [self saveToURL:[self fileURL] ofType:[self fileType] forSaveOperation:NSSaveOperation delegate:nil didSaveSelector:nil contextInfo:NULL];
        wasRenamed = NO;
    }
    else
    {
        [super saveDocument:sender];
    }
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,您还需要检查以下可能性:

  1. 要求应用重命名文档
  2. 重命名的文件随后被另一个应用程序修改/移动
  3. 用户去保存文档

此时,您希望出现通常的警告表。可能可以通过以下方式来完成:

- (void)renameDocumentTo:(NSString *)newName
{
    // Do the rename

    [self setFileURL:newURL];
    wasRenamed = YES; // MUST happen after -setFileURL:
}

- (void)setFileURL:(NSURL *)absoluteURL;
{
    if (![absoluteURL isEqual:[self fileURL]]) wasRenamed = NO;
    [super setFileURL:absoluteURL];
}

- (void)setFileModificationDate:(NSDate *)modificationDate;
{
    if (![modificationDate isEqualToDate:[self fileModificationDate]]) wasRenamed = NO;
    [super setFileModificationDate:modificationDate];
}
Run Code Online (Sandbox Code Playgroud)

否则,我能看到的您唯一的其他选择是使用一些自定义参数调用标准保存/写入方法之一,这些参数提示您的文档子类移动当前文档而不是实际保存它。我认为会更棘手。也许定义你自己的NSSaveOperationType

通过这种技术,文档系统应该理解重命名是类似保存操作的一部分,但需要进行大量实验才能确定。