防止当NSDocument文件(编程)重命名时出现警告

防止当NSDocument文件(编程)重命名时出现警告

问题描述:

我的应用程序允许用户重命名当前打开的文档。这是微不足道的,并且工作正常,有一个非常烦人的错误,我无法弄清楚。当文件被重命名时,AppKit(友善地)在下次尝试保存文档时提醒用户。用户说“OK”,一切正常。当应用程序外部的某些内容改变了文档时,这是有意义的,但当文档本身实际上完成时则不行。防止当NSDocument文件(编程)重命名时出现警告

的代码是这样的:

-(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和修改日期就足够了,但遗憾的是事实并非如此。可可仍然会产生警告。

我试过改变顺序(在文档上设置新的URL,然后重命名文件),但这没有帮助。

我也试过在CocoaDev对旧的文章在用户提出了一个修正:

[self performSelector:@selector(_resetMoveAndRenameSensing)]; 

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

如果任何人都可以阐明我可能需要做的事情,那很好,谢谢!

+0

我已经开始赏金寻求帮助。不幸的是,我真的无处可去。一个简单的测试用例就是创建一个打开一个.txt文件(或其他任何东西)的空白文档应用程序,添加一个菜单项,其操作将打开的文件重命名为其他内容(并使用新URL更新文档对象)。我尝试在重命名后第一次尝试保存文件时规避警告。 – d11wtq 2010-12-07 11:27:19

+0

哦,如果文档正在编辑,这需要工作。如果存在未保存的更改,则保存到磁盘,关闭文档,移动文件然后重新打开它可能会产生不良影响。 – d11wtq 2010-12-07 11:28:41

在主文档中没有太多这方面的内容。相反,看看10.5发行说明:http://developer.apple.com/library/mac/#releasenotes/Cocoa/AppKitOlderNotes.html%23X10_5Notes标题下“NSDocument检查修改文件在保存时间”

(在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. 用户前往保存文档

那时你想要通常的警告表出现。或许可以通过类似来完成:

- (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

有了这种技术,文档系统应该明白,重命名是类似保存的操作的一部分,但需要相当多的实验才能确定。

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

我看到这个问题是启动并运行了一段时间,所以告诉你读reference将没有任何好处我想..

希望我帮助一点点,虽然它不修复你的问题直接

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

  • 我超载saveDocumentWithDelegate:didSaveSelector:contextInfo:确定保存URL和文件类型(指派那些self);如果旧fileURL存在,我将其移至新位置
  • 里面saveDocumentWithDelegate:didSaveSelector:contextInfo:我的呼叫重定向到[self saveToURL:self.fileURL ofType:self.fileType forSaveOperation:NSSaveAsOperation completionHandler: ...]而不是[super saveDocumentWithDelegate:didSaveSelector:contextInfo:]

这对我的作品。