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

时间:2010-12-03 09:17:54

标签: objective-c cocoa macos nsdocument

我的应用程序允许用户重命名当前打开的文档。这是微不足道的,并且工作正常,有一个我无法弄清楚的非常烦人的bug。重命名文件时,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]];
}

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

我已尝试更改订单(在文档上设置新网址,然后重命名文件),但这没有帮助。

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

[self performSelector:@selector(_resetMoveAndRenameSensing)];

然而,即使这并没有停止警告,我猜测 是使用记录的API执行此操作的正确方法。当用户单击项目树上的文件并将其重命名为其他内容时,Xcode如何处理事物。它不会警告用户重命名,因为用户实际执行了重命名。

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

3 个答案:

答案 0 :(得分:3)

主要文档中没有太多内容。相反,请查看标题为“NSDocument在节省时间检查已修改文件”标题下的10.5版本说明:http://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKitOlderNotes.html%23X10_5Notes

(在Xcode的情况下,它有很长的历史,如果不对项目中的文件使用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];
    }
}

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

  1. 要求应用重命名文档
  2. 然后由另一个应用
  3. 修改/移动重命名的文件
  4. 用户去保存文档
  5. 此时你需要通常的警告表。可能可以通过以下方式实现:

    - (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];
    }
    

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

    使用这种技术,doc系统应该理解重命名是类似于类似操作的一部分,但是需要相当多的实验才能确定。

答案 1 :(得分:0)

是否有可能以编程方式为用户回答问题? 或者您可以在重命名后立即保存,这样用户可以一次性获得每个答案。

我发现这个问题已经启动并运行了一段时间,因此告诉您阅读reference我不会做任何好事。

希望我帮助了一点,虽然它没有直接解决你的问题

答案 2 :(得分:0)

很多灵感来自@ Mike的回答,我通过将NSSaveOperation重新路由到NSSaveAsOperation,得到了“移动到”消息,不再显示。在我的NSDocument子类中:

  • 我重载saveDocumentWithDelegate:didSaveSelector:contextInfo:以确定保存网址和文档类型(将其分配给self);如果旧的fileURL存在,我将其移动到新位置
  • saveDocumentWithDelegate:didSaveSelector:contextInfo:内,我将来电重定向到[self saveToURL:self.fileURL ofType:self.fileType forSaveOperation:NSSaveAsOperation completionHandler: ...]而不是[super saveDocumentWithDelegate:didSaveSelector:contextInfo:]

这适合我。