如何将NSDocumentController子类化为一次只允许一个doc

时间:2013-03-04 01:26:23

标签: objective-c cocoa nsdocumentcontroller

我正在尝试创建一个基于文档的核心数据应用程序,但限制条件是一次只能查看一个文档(这是一个音频应用程序,对很多文档制作噪音没有意义立刻)。

我的计划是以一种不需要将其链接到任何菜单操作的方式继承NSDocumentController。这已经合理地进行了但是我遇到了一个问题,这让我对我的方法提出了一些质疑。

以下代码大部分都有效,除非用户执行以下操作: - 尝试打开一个已打开现有“脏”文档的文档 - 点击取消保存/不保存/取消警报(这可以正常) - 然后再次尝试打开文档。由于某种原因,即使打开对话框,也不会再次调用openDocumentWithContentsOfURL方法。

任何人都可以帮我解决原因吗?或者或许请指出一个如何做到这一点的例子?这感觉就像一些必须由少数人实现的东西,但我找不到10.7+的例子。

- (BOOL)presentError:(NSError *)error
{
    if([error.domain isEqualToString:DOCS_ERROR_DOMAIN] && error.code == MULTIPLE_DOCS_ERROR_CODE)
        return NO;
    else
        return [super presentError:error];
}

- (id)openUntitledDocumentAndDisplay:(BOOL)displayDocument error:(NSError **)outError
{
    if(self.currentDocument) {
        [self closeAllDocumentsWithDelegate:self
                        didCloseAllSelector:@selector(openUntitledDocumentAndDisplayIfClosedAll: didCloseAll: contextInfo:)
                                contextInfo:nil];

        NSMutableDictionary* details = [NSMutableDictionary dictionary];
        [details setValue:@"Suppressed multiple documents" forKey:NSLocalizedDescriptionKey];
        *outError = [NSError errorWithDomain:DOCS_ERROR_DOMAIN code:MULTIPLE_DOCS_ERROR_CODE userInfo:details];
        return nil;
    }

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

- (void)openUntitledDocumentAndDisplayIfClosedAll:(NSDocumentController *)docController
                                      didCloseAll: (BOOL)didCloseAll
                                      contextInfo:(void *)contextInfo
{
    if(self.currentDocument == nil)
        [super openUntitledDocumentAndDisplay:YES error:nil];
}

- (void)openDocumentWithContentsOfURL:(NSURL *)url
                              display:(BOOL)displayDocument
                    completionHandler:(void (^)(NSDocument *document, BOOL documentWasAlreadyOpen, NSError *error))completionHandler NS_AVAILABLE_MAC(10_7)
{
    NSLog(@"%s", __func__);
    if(self.currentDocument) {
        NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:[url copy], @"url",
                                                                        [completionHandler copy], @"completionHandler",
                                                                        nil];
        [self closeAllDocumentsWithDelegate:self
                        didCloseAllSelector:@selector(openDocumentWithContentsOfURLIfClosedAll:didCloseAll:contextInfo:)
                                contextInfo:(__bridge_retained void *)(info)];
    } else {
        [super openDocumentWithContentsOfURL:url display:displayDocument completionHandler:completionHandler];
    }
}

- (void)openDocumentWithContentsOfURLIfClosedAll:(NSDocumentController *)docController
                                     didCloseAll: (BOOL)didCloseAll
                                     contextInfo:(void *)contextInfo
{
    NSDictionary *info = (__bridge NSDictionary *)contextInfo;
    if(self.currentDocument == nil)
        [super openDocumentWithContentsOfURL:[info objectForKey:@"url"] display:YES completionHandler:[info objectForKey:@"completionHandler"]];
}

2 个答案:

答案 0 :(得分:1)

Apple's cocoa-dev mailing list上有一个非常丰富的信息交流,描述了为了你的目的而为了NSDocumentController而继承你需要做些什么。结果是在打开新文档时关闭现有文档。

你可能会考虑的其他事情是当窗口的主窗口(例如,将NSWindowDidResignMainNotification发送到窗口的委托)时静音或停止播放文档,如果只是为了避免强制似乎是人为的限制。用户。

答案 1 :(得分:0)

我知道已经有一段时间了,但万一它能帮助别人......

我认为这是一个类似的问题,解决方案是在我的自定义DocumentController 打开文档时调用完成处理程序,例如:

- (void)openDocumentWithContentsOfURL:(NSURL *)url display:(BOOL)displayDocument completionHandler:(void (^)(NSDocument * _Nullable, BOOL, NSError * _Nullable))completionHandler {

    if (doOpenDocument) {
        [super openDocumentWithContentsOfURL:url display:displayDocument completionHandler:completionHandler];
    } else {
        completionHandler(NULL, NO, NULL);
    }
}

当我添加completionHandler(NULL, NO, NULL);时,它开始工作超过一次。