Как создать подкласс NSDocumentController, чтобы разрешить только один документ за раз

Я пытаюсь создать приложение Core Data, основанное на документах, но с ограничением, что одновременно можно просматривать только один документ (это аудио-приложение, и для многих документов не имеет смысла шуметь сразу),

Мой план состоял в том, чтобы создать подкласс 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 ответа

Решение

Существует очень информативный обмен в списке рассылки Apple по разработке какао, который описывает, что вы должны сделать, чтобы подкласс NSDocumentController для ваших целей. В результате существующий документ закрывается при открытии нового.

Что-то еще, что вы могли бы рассмотреть, это отключить или прекратить воспроизведение документа, когда его окно уходит в отставку основной (т.е. отправляет NSWindowDidResignMainNotification делегату окна), хотя бы для того, чтобы избежать форсирования того, что может показаться искусственным ограничением для пользователя.

Я знаю, что это было давно, но в случае, если это помогает другим....

У меня была похожая проблема, и я решил вызвать обработчик завершения, когда мой пользовательский 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); это начало работать больше, чем один выстрел.

Другие вопросы по тегам