6

我的应用程序允许用户重命名当前打开的文档。这是微不足道的,并且工作正常,有一个我无法弄清楚的非常烦人的错误。当文件被重命名时,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 仍然会产生警告。

我尝试更改顺序(在文档上设置新 URL,然后重命名文件),但这无济于事。

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

[self performSelector:@selector(_resetMoveAndRenameSensing)];

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

我需要做什么?

4

3 回答 3

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's 通常的警告,如下所示:

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

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

于 2010-12-10T12:38:38.287 回答
1

受到@Mike 回答的很大启发,我得到了“移至”消息,不再通过重新路由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:]

这对我有用。

于 2015-12-11T07:45:39.340 回答
0

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

我看到这个问题已经出现并运行了一段时间,所以告诉你阅读参考资料我猜不会有任何好处..

希望我能帮上一点忙,虽然它不能直接解决你的问题

于 2010-12-10T12:46:58.670 回答