Хобрук: Ваш путь к мастерству в программировании

Приложение на основе документов не восстанавливает документы с нефайловыми URL-адресами

У меня есть приложение на основе NSDocument с подклассом NSDocumentController. Мой NSDocument работает как с URL-адресами файлов, так и с URL-адресами с настраиваемой схемой, в которой используется веб-служба.

Я выполняю большую часть загрузки и сохранения, используя собственный код, включая -saveToURL:ofType:forSaveOperation:completionHandler:. +autosavesInPlace возвращает YES.

У меня проблема: документы с настраиваемой схемой URL-адресов не восстанавливаются при запуске. Документы с файловой схемой URL - это как обычные документы, сохраняемые в файлы, так и безымянные документы, которые сохраняются автоматически.

После выхода из открытых серверных документов и выхода из приложения методы NSDocument не вызываются при перезапуске. В частности, ни один из четырех инициализаторов не вызывается:

  • -в этом
  • –InitWithContentsOfURL: ofType: error:
  • –InitForURL: withContentsOfURL: ofType: ошибка:
  • –InitWithType: ошибка:

Метод NSDocumentController -reopenDocumentForURL:withContentsOfURL:display:completionHandler: также не вызывается.

Как и когда кодируется восстанавливаемое состояние документов? Как и когда они декодируются?


Ответы:


1

NSDocument отвечает за кодирование своего восстанавливаемого состояния в -encodeRestorableStateWithCoder:, а NSDocumentController отвечает за декодирование восстанавливаемого состояния документов и повторное открытие документов в +restoreWindowWithIdentifier:state:completionHandler:. См. Полезные комментарии в NSDocumentRestoration.h.

Когда NSDocument кодирует URL-адрес, он, похоже, использует методы закладок NSURL. Проблема в том, что эти методы работают только с URL-адресами файловой системы. (Возможно, будут кодироваться нефайловые URL-адреса, но они не будут декодироваться должным образом.)

Чтобы решить эту проблему, переопределите кодировку экземпляров NSDocument, которые используют настраиваемую схему, а также декодирование этих документов.

Подкласс NSDocument:

- (void) encodeRestorableStateWithCoder:(NSCoder *) coder {
    if ([self.fileURL.scheme isEqualToString:@"customscheme"])
        [coder encodeObject:self.fileURL forKey:@"MyDocumentAutoreopenURL"];
    else
        [super encodeRestorableStateWithCoder:coder];
}

Подкласс NSDocumentController:

+ (void) restoreWindowWithIdentifier:(NSString *) identifier
                               state:(NSCoder *) state
                   completionHandler:(void (^)(NSWindow *, NSError *)) completionHandler {

    NSURL *autoreopenURL = [state decodeObjectForKey:@"MyDocumentAutoreopenURL"];
    if (autoreopenURL) {
        [[self sharedDocumentController]
         reopenDocumentForURL:autoreopenURL
         withContentsOfURL:autoreopenURL
         display:NO
         completionHandler:^(NSDocument *document, BOOL documentWasAlreadyOpen, NSError *error) {

             NSWindow *resultWindow = nil;
             if (!documentWasAlreadyOpen) {

                 if (![[document windowControllers] count])
                     [document makeWindowControllers];

                 if (1 == document.windowControllers.count)
                     resultWindow = [[document.windowControllers objectAtIndex:0] window];
                 else {
                     for (NSWindowController *wc in document.windowControllers)
                         if ([wc.window.identifier isEqual:identifier]) {
                             resultWindow = wc.window;
                             break;
                         }
                 }
             }
             completionHandler(resultWindow, error);
         }
         ];
    } else
        [super restoreWindowWithIdentifier:identifier
                                     state:state
                         completionHandler:completionHandler];
}

Поведение или обработчик завершения следует из комментария Apple к методу в NSDocumentRestoration.h и должен быть примерно таким же, как у super.

20.12.2012

2

Кодирование состояния окна включено двумя методами на NSWindow. Вызов setRestorable: в окне помечает его как тот, который можно сохранить и восстановить при перезапуске, а затем вызов setRestorationClass: позволяет указать класс, который будет обрабатывать воссоздание этого сохраненного окна.

По умолчанию AppKit устанавливает NSDocumentController как класс восстановления окон, управляемых NSDocument объектами. Фактическое восстановление выполняется путем вызова метода +restoreWindowWithIdentifier:state:completionHandler:, определенного протоколом NSWindowRestoration. Для документов NSDocumentController реализует этот метод и воссоздает объект NSDocument на основе состояния, закодированного в экземпляре NSCoder, переданном в метод.

Итак, теоретически, если бы вы создали подкласс NSDocumentController и переопределили этот метод, это дало бы вам возможность восстановить документы, сохраненные механизмом восстановления состояния. Однако, насколько мне известно, ключи, используемые NSDocumentController для хранения состояния, нигде не задокументированы, поэтому я не думаю, что существует надежный способ восстановления непосредственно из состояния, которое NSDocumentController сохраняет само.

Для поддержки этого вам, вероятно, потребуется кодировать все состояние документа самостоятельно, реализовав -encodeRestorableStateWithCoder: в кодируемом NSWindow, и / или реализовать метод делегата window:willEncodeRestorableState: для окна. Оба этих метода передают вам NSCoder экземпляр, который вы можете использовать для кодирования своего состояния. Здесь вы должны закодировать свой настраиваемый URL-адрес вместе с любыми другими связанными данными, которые вам нужны для сохранения / восстановления вашего состояния. Затем вы расшифруете это состояние в методе restoreWindowWithIdentifier:state:completionHandler:.

Поскольку у вас будут некоторые документы с обычными URL-адресами файлов и некоторые с вашими пользовательскими URL-адресами, я бы подошел к этому, создав отдельный класс, отвечающий за декодирование состояния документа, и установил его в качестве класса восстановления только для ваших документов с пользовательскими URL-адресами, оставив NSDocumentController, чтобы обрабатывать документы с URL-адресами файлов за вас.

18.12.2012
  • Это было большим подспорьем в начале работы. Оказывается, история более сложная: на самом деле это NSDocument, а не NSWindow, который отвечает за кодирование состояния document (пронумерованный идентификатор, url, имеет последние изменения, тип) в своей собственной реализации -encodeRestorableStateWithCoder:. NSDocumentController использует эту информацию о состоянии для восстановления документа, затем вызывает -makeWindowControllers и NSApplication (или обработчик завершения NSApplication?) Восстанавливает окно. Кроме того, при использовании настраиваемого подкласса NSDocumentController, AppKit устанавливает этот класс как restorationClass. 20.12.2012
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

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

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..