Приложение OSX на основе документов - ограничьте количество открытых документов одним

Я пытаюсь выяснить, как ограничить мое приложение на основе NSDocument одним открытым документом за раз. Это быстро становится беспорядком.

Кто-нибудь смог сделать это простым и надежным способом?

//// РЕДАКТИРОВАТЬ //// Я хотел бы иметь возможность предложить пользователю сохранить существующий открытый документ и закрыть его перед созданием / открытием нового документа.

//// РЕДАКТИРОВАТЬ 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];
}

2 ответа

Решение

Это не будет легким решением, так как это довольно сложный класс, но я бы посоветовал вам подкласс NSDocumentController и зарегистрируйте свой собственный, который запрещает открывать за определенное количество документов. Это позволит вам предотвратить такие вещи, как открытие файлов, перетаскивая их на значок приложения в доке или открывая в 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: с self в качестве делегата и вновь созданной подпрограммы в качестве селектора
  3. Получив селектор, удалите сохраненные аргументы или повторите команды с сохраненными аргументами.

Обратите внимание, что шаги 2 и 3 могут быть выполнены с задержкой performSelector

Я не пробовал это сам (остальное я делал раньше), но похоже, что это должно сработать.

Вот решение, которое я выбрал. Все это находится в подклассе 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];

}

Кроме того, мне, к сожалению, нужно было убрать опцию "Открыть недавние" из главного меню. Я не понял, как обойти эту ситуацию.

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