Как вы получаете доступ к представлениям, определенным в приложении на основе NSDocument? Есть ли ошибки в шаблоне проекта? - PullRequest
0 голосов
/ 21 февраля 2020

Хорошо, это поставило меня в тупик. Давний iOS dev пытался написать свое первое приложение для MacOS, и я хотел, чтобы оно было основано на документах. Я начинаю с шаблона по умолчанию и запускаю его. Все кажется работает должным образом.

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

Теперь вот код, взятый прямо из первого после выполнения «нового проекта» ...

import Cocoa

class Document: NSDocument {

    override init() {
        super.init()
        // Add your subclass-specific initialization here.
    }

    override class var autosavesInPlace: Bool {
        return true
    }

    override var windowNibName: NSNib.Name? {
        // Returns the nib file name of the document
        // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this property and override -makeWindowControllers instead.
        return NSNib.Name("Document")
    }

    override func data(ofType typeName: String) throws -> Data {
        // Insert code here to write your document to data of the specified type, throwing an error in case of failure.
        // Alternatively, you could remove this method and override fileWrapper(ofType:), write(to:ofType:), or write(to:ofType:for:originalContentsURL:) instead.
        throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
    }

    override func read(from data: Data, ofType typeName: String) throws {
        // Insert code here to read your document from the given data of the specified type, throwing an error in case of failure.
        // Alternatively, you could remove this method and override read(from:ofType:) instead.
        // If you do, you should also override isEntireFileLoaded to return false if the contents are lazily loaded.
        throw NSError(domain: NSOSStatusErrorDomain, code: unimpErr, userInfo: nil)
    }
}

В «Document.xib» я вижу владельца файла установлен в этот класс Document, но, как ни странно, Interface Builder показывает, что в нем уже определено выходное окно «окно», которое уже подключено. То же самое со свойством делегата. Что меня смущает, так это то, что не имеет ни кода, называемого "окном" в коде, ни базового класса NSDocument, и, насколько я понимаю, этого не должно быть, потому что окно не является частью NSDocument, но, скорее, он принадлежит и управляется классом NSWindowController, для которого документ может указывать один или несколько (но реализация по умолчанию просто создает один).

Итак ... где, черт возьми это выход «окна», указывающий на?

Еще более запутанно, так как класс документа был задан как владелец файла, просто для теста я добавил свой собственный выход с именем mainTextField, который я хотел назначить для уже существующее текстовое поле в XIB. Вот мое определение ...

@IBOutlet private weak var mainTextField : NSTextField!

Затем я подключил розетку в Интерфейсном Разработчике к уже существующей метке, просто чтобы посмотреть, смогу ли я обновить ее из кода. Однако при запуске приложения розетка по-прежнему равна нулю!

Примечание. Добавление этой розетки и ее подключение в Interface Builder приводит к изменению кода only на шаблон проекта по умолчанию, если Вы хотели попробовать это сами.

Итак, мои вопросы таковы:

  1. Где, черт возьми, это выход window, определенный в классе NSDocument, который показывает в Интерфейсном Разработчике (через местозаполнитель FilesOwner) и
  2. Почему мои розетки не подключены? и
  3. Является ли мой класс документов не фактическим владельцем для WindowController? Если нет, то почему это так отображается в Интерфейсном Разработчике?

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

NSDocument
  |
   - NSWindowController* (stored in the document's `windowControllers` property)
       |
        -NSViewController (stored in the window controller's `contentViewController` property

* can be more than one, but by default, only one is created,
  loaded from the XIB defined by the given NIB name.

Вы действительно не должны иметь прямой контент в окне (т.е. -определенный NSTextLabel, уже присутствующий в XIB, на самом деле не должен быть там), и вместо этого он должен использовать ваш собственный NSViewController, которому присваивается свойство contentViewController NSWindowController (опять же, по умолчанию, но это может быть несколько), но где вы на самом деле должны делать это назначение, если вы просто используете значение по умолчанию NSWindowController, которое загружается через windowNibName? Не существует значения по умолчанию, так как contentViewController равно nil, поэтому в каком случае окно по умолчанию получает свое представление root в первую очередь?

Итак, есть ли здесь ошибки или нет? Я неправильно понимаю, как все это должно работать? Я следовал документации (которая редка) и единственным учебникам, которые я нашел: «Начни с собственного кода с нуля», заставляя меня думать, что - это проблема с этим кодом. Но Apple, я не думаю, сделал бы такую ​​ошибку, если бы это было правдой! Это так запутанно !!!

...