Открытие приложения на основе NSDocument загружает два окна - PullRequest
0 голосов
/ 26 апреля 2019

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

override func makeWindowControllers() {
    // Returns the Storyboard that contains your Document window.
    let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
    let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! NSWindowController
    self.addWindowController(windowController)
}

override func read(from data: Data, ofType typeName: String) throws {

    if let fileString = String(data: data, encoding: String.Encoding.utf8) {

        makeWindowControllers()

        guard let vc = windowControllers.first?.contentViewController as? ViewController else {
            throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
        }

        guard let inputString = String(data: data, encoding: .utf8) else {
            throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
        }

        let doc = JsonConverter().convertToJSONFrom(string: inputString)

        if let a = doc["a"] as? String {
            vc.leftTextView.string = a
        }

        if let b = doc["b"] as? String {
            vc.rightTextView.string = b
        }

    } else {
        throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
    }
}

Main UI

Я не понимаю, откуда идет второй (справа).

edit: Я только что заметил, что если дважды щелкнуть сохраненный файл, я получаю эту ошибку, которая, как ни странно, НЕ запускается ни одним из этих NSErrors в функции read ().

Fwiw, Открыть из меню - это то, что я имел в виду выше.

изменить 2: Исправление. «Иногда» он открывает два окна. Но даже когда это делает, оба пусты. Чего я не понимаю, так это того, что эта функция чтения настолько проста, что не так уж много ошибок. Такое ощущение, что под капотом все идет вбок.

Error when double clicking file.

1 Ответ

1 голос
/ 26 апреля 2019

Я не понимаю, откуда идет второй (справа).

Похоже, что это происходит от вашей read() функции, которая вызывает makeWindowControllers(). Из документации :

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

Когда документ открыт, он, конечно, также читается, поэтому makeWindowControllers() вызывается дважды: один раз из-за встроенного поведения открытия документа и один раз из-за переопределения read().

Исправление. «Иногда» он открывает два окна. Но даже когда это делает, оба пусты.

Возможно, у вас есть случайная ошибка, которая не позволяет документу даже дозвониться до read().

если дважды щелкнуть сохраненный файл, я получаю эту ошибку

Это поддерживает идею, что что-то идет не так, прежде чем вы даже доберетесь до read(). Вы можете легко это выяснить, поместив сообщение журнала в read() и проверив консоль на наличие этого сообщения после случая, когда открывается только одно окно. Кроме того, есть ли у вас какие-либо методы application(open...), переопределенные в вашем делегате приложения? Возможно, один из них ответственен за ошибку.

Обновление:

Немного поработав с простым документным проектом, я обнаружил, что NSDocument действительно вызывает для вас makeWindowControllers(), но делает это после и вызывает read(). Точка останова в вашем методе read() покажет, что контроллеров представления нет, поскольку makeWindowControllers() еще не был вызван. Вот мой read() метод:

override func read(from data: Data, ofType typeName: String) throws {
    // makeWindowControllers();
    guard let text = String(bytes: data, encoding: .utf8) else { return }
    self.content = text
}

Если я раскомментирую вызов makeWindowControllers(), у меня появится тот же симптом, о котором вы спрашиваете: открываются два окна, и только одно из них показывает содержимое. Однако, если я создаю новый документ, я получаю только одно окно, потому что метод read() никогда не вызывается.

Так что на данный момент это базовое приложение. Контроллер представления имеет пару выходов и устанавливает текст в функции textDidChange NSTextViewDelegate. Но это все. App делегат по умолчанию, затем класс Document. Если я не вызываю makeWindowControllers, то windowControllers пуст. Если я это называю, то у меня есть 1 контроллер, который я использую для обновления пользовательского интерфейса. Не совсем уверен, как обойти это.

Вы пытаетесь сделать слишком много в вашем read() методе. NSDocument очень ориентирован на MVC, и вы можете рассматривать документ как своего рода контроллер - он связывает представления и данные вместе. Метод read() предназначен для того, чтобы вы могли читать данные, а представления не создаются до этого. Я думаю, что это, вероятно, потому что данные могут определить, какой вид создать. Мой класс документа имеет свойство content, которое представляет собой просто строку, а read() просто берет данные из файла и вставляет их в строку. В моем случае makeWindowControllers() вызывается для меня автоматически, и мое переопределение использует content для настройки окна:

override func makeWindowControllers() {
    // Returns the Storyboard that contains your Document window.
    let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil)
    let windowController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("Document Window Controller")) as! WindowController
    windowController.text = self.content
    self.addWindowController(windowController)
}

Кроме того, если я закомментирую вызов makeWindowControllers, он никогда не будет вызываться при открытии файла. Регистрация доказывает, что он вызывается только один раз с ручным вызовом и ноль без него.

У меня нет хорошего объяснения этому, если ваш лог-оператор находится в makeWindowControllers(). Это не согласуется с тем, что я вижу, поэтому я бы попросил вас: а) проверить вашу работу и б) добавить больше информации здесь, либо в комментарии, либо в вашем вопросе. Опять же, я вижу, что makeWindowControllers() вызывают без необходимости явного вызова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...