0

我试图弄清楚如何将基于 NSDocument 的应用程序一次限制为一个打开的文档。它很快变得一团糟。

有没有人能够以简单可靠的方式做到这一点?

////EDIT//// 我希望能够提示用户保存现有的打开文档并在创建/打开新文档之前将其关闭。

////EDIT 2 如果有任何文档正在打开,我现在正试图返回一个带有适当消息的错误——但是,错误消息没有显示我的 NSLocalizedKeyDescription。这是在我的 NSDocumentController 子类中。

-(id)openUntitledDocumentAndDisplay:(BOOL)displayDocument error:(NSError **)outError{


if([self.documents count]){

    NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObject:@"Only one document can be open at a time. Please close your document." forKey:NSLocalizedDescriptionKey];

    *outError = [NSError errorWithDomain:@"Error" code:192 userInfo:dict];

    return nil;
}
return     [super openUntitledDocumentAndDisplay:displayDocument error:outError];
}
4

2 回答 2

3

这不是一个简单的解决方案,因为它是一个非常复杂的类,但我建议你继承NSDocumentController并注册你自己的子类,这会禁止打开超过一定数量的文档。这将允许您通过将文件放在 Dock 中的应用程序图标上或在 finder 中打开来防止打开文件之类的事情,这两者都绕过了Open菜单项。

您仍然需要覆盖 GUI/菜单激活码,以防止Open...在您已经打开文档时可用,但这只是为了确保您不会混淆用户。

您的文档控制器需要在任何其他文档控制器之前创建,但这很容易通过DocumentController在您的实例中放置一个实例MainMenu.xib并确保将类设置为您的子类。(这将导致它调用-sharedDocumentController,这将创建您的实例。)

然后,在您的文档控制器中,您将需要覆盖:

- makeDocumentForURL:withContentsOfURL:ofType:error:
- makeUntitledDocumentOfType:error:
- makeDocumentWithContentsOfURL:ofType:error:

检查并查看文档是否已打开并返回 nil,将错误指针设置为显示适当消息的新创建的错误 ( NSLocalizedDescriptionKey)。

那应该处理拖放,applescript等的情况。

编辑 至于您对开幕事件的关闭/保存提示的附加请求,这是一个更棘手的问题。你可以:

  1. 保存信息(基本上是make请求的参数)
  2. -closeAllDocumentsWithDelegate:didCloseAllSelector:contextInfo:withself作为委托发送,将新创建的例程作为选择器发送
  3. 当您收到选择器时,要么清除保存的参数,要么使用保存的参数重新执行命令。

请注意,第 2 步和第 3 步可能需要延迟完成performSelector

我自己没有尝试过这个(我之前做过的其余部分),但它似乎应该工作。

于 2013-04-13T22:03:34.287 回答
0

这是我最终得到的解决方案。所有这些都在 NSDocumentController 子类中。

- (NSInteger)runModalOpenPanel:(NSOpenPanel *)openPanel forTypes:(NSArray *)extensions{

    [openPanel setAllowsMultipleSelection:NO];

    return [super runModalOpenPanel:openPanel forTypes:extensions];
}

-(NSUInteger)maximumRecentDocumentCount{
    return 0;
}


-(void)newDocument:(id)sender{

    if ([self.documents count]) {

        [super closeAllDocumentsWithDelegate:self
                         didCloseAllSelector:@selector(newDocument:didCloseAll:contextInfo:) contextInfo:(void*)sender];

    }
    else{
        [super newDocument:sender];
    }
}

- (void)newDocument:(NSDocumentController *)docController  didCloseAll: (BOOL)didCloseAll contextInfo:(void *)contextInfo{

    if([self.documents count])return;

    else [super newDocument:(__bridge id)contextInfo];

}

-(void)openDocument:(id)sender{

    if ([self.documents count]) {

        [super closeAllDocumentsWithDelegate:self
                         didCloseAllSelector:@selector(openDocument:didCloseAll:contextInfo:) contextInfo:(void*)sender];

    }
    else{
        [super openDocument:sender];
    }



}

- (void)openDocument:(NSDocumentController *)docController  didCloseAll: (BOOL)didCloseAll contextInfo:(void *)contextInfo{

    if([self.documents count])return;
    else [super openDocument:(__bridge id)contextInfo];

}

此外,不幸的是,我需要从主菜单中删除“打开最近”选项。我还没有想出如何解决这种情况。

于 2013-04-14T16:43:51.887 回答