1

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

我的计划是以一种不需要将其链接到任何菜单操作的方式对 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"]];
}
4

2 回答 2

1

在Apple 的 cocoa-dev 邮件列表上有一个非常有用的交流,它描述了你必须做什么才能NSDocumentController为你的目的进行子类化。结果是在打开新文档时关闭现有文档。

您可能会考虑的其他事情是在其窗口退出主窗口时静音或停止播放文档(即,发送NSWindowDidResignMainNotification给窗口的委托),如果只是为了避免对用户施加看似人为的限制。

于 2013-03-04T02:12:13.983 回答
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);它开始工作不止一次。

于 2017-08-29T05:08:54.720 回答