NSWindowController разъяснение понимания - PullRequest
40 голосов
/ 10 сентября 2010

Я несколько раз использовал NSWindowController в проектах и ​​чувствую, что у меня есть (очень) грубое понимание концепций этого важного класса.Что я хотел бы сделать с этим постом, так это уточнить / исправить мои собственные представления и, надеюсь, помочь другим учащимся сделать первый шаг к пониманию.Это с первого взгляда концепции, обзор и лучшие практики, которые я считаю наиболее полезными и часто отсутствуют в документации.Вот мой взгляд на NSWindowController (вопросы выделены жирным шрифтом):

  • Подкласс NSWindowController (NSWC) существует (концептуально) как раз под каждым кончиком окна, выступая в качестве связующего звена между элементами пользовательского интерфейса имоделировать объекты, которые они контролируют / представляют.По сути, каждое окно в вашем приложении должно иметь свой собственный подкласс NSWC.
  • Владельцем nib-файла всегда должен быть подкласс NSWC. Это относится даже к приложению MainMenu.xib?
  • Свойство NSWC window всегда должно быть связано с NSWindow в InterfaceBuilder.
  • Вы должны переопределитьМетод 'init', использующий [super initWithWindowNibName:], так что когда вы ссылаетесь на [mycontroller window], он загружает перо. Должно ли это также относиться к NSWC для окна MainMenu.xib, даже если оно открывается при запуске?
  • NSWC не должен выполнять слишком большую работу - он должен простопередавать сообщения экземплярам объектов и представлять эти объекты в пользовательском интерфейсе.
  • Он может изменять пользовательский интерфейс, используя привязку, или выступать в качестве делегата для таблиц и т. д., или активно изменяя элементы пользовательского интерфейса, когда он наблюдает заизменение или сочетание любого из вышеперечисленного (какой вы используете, кажется, дело вкуса, с за и против со всех сторон).
  • NSWC может создавать экземпляры других NSWC при необходимости (дляНапример, при открытии одноразового подокна).
  • Используйте [mycontroller showWindow:nil] для отображения соответствующего окна спереди.Если вы хотите, чтобы окно отображалось в виде листа, используйте что-то вроде:

    NSWindowController* mycontroller = [[MyController alloc] init];
    [NSApp beginSheet: [mycontroller window]
       modalForWindow: [self window] 
        modalDelegate: self 
       didEndSelector: @selector(didEndMySheet:returnCode:contextInfo:)
          contextInfo: nil];
    

* didEndSelector: должен быть методом NSWC родительского окна и иметь доступ к иотпустите «mycontroller» с помощью [sheet windowController].- Чтобы закрыть окно, вызовите метод performClose: окна NSWC.

Некоторые вопросы:

  • Если NSWC окна MainMenu также является приложениемделегат, или это должен быть другой класс?
  • В том же духе, должен ли основной NSWC обрабатывать файлы (перетаскивание / открытие и открытие), или он должен быть передан делегату приложения, или это простовопрос вкуса?

Пожалуйста, поправьте меня, если что-то из этого является плохой практикой или просто неправильно.Я хочу уточнить мое понимание NSWindowController, поэтому любые дополнения (в виде лучших практик, опытов, полезностей) будут высоко оценены.

Спасибо, Лори

Ответы [ 2 ]

30 голосов
/ 10 сентября 2010

Для чего собственно оконные контроллеры?

Контроллеры окон - это инструменты для загрузки окна из файла NIB и для управления памятью ресурсов, выделенных в NIB. До того момента, когда NSWindowControllers нужно было написать один и тот же код для каждого окна или изобрести собственный класс оконного контроллера.

Конечно, они также являются контроллерами в смысле Модель / Представление / Контроллер, поэтому они являются подходящим местом для соединения видов из окна с объектами модели. Для этого им часто нужно выступать в качестве делегата или источника данных для объекта представления. Итак, вы правильно поняли эту часть.

Также оконные контроллеры являются инструментом для повторного использования кода. Это позволяет легко удалить класс оконного контроллера и его XIB / NIB в другой проект и использовать его там.

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

WindowControllers и MainMenu.xib

MainMenu.xib - это совсем другое, здесь вы не можете использовать оконный контроллер. Этот NIB загружается NSApplication, поэтому это должен быть «Владелец файлов». Невозможно получить оконный контроллер между NSApplication и NIB. Также нет необходимости использовать оконный контроллер для управления памятью, поскольку объект приложения живет в течение всего времени выполнения программы, поэтому ему не нужно очищать свои ресурсы от NIB, когда он освобождается.

Если вам действительно нужен оконный контроллер для основного окна, вы не можете поместить его в MainMenu.xib.

Надеюсь, это поможет. Наверное, о контроллерах окон можно сказать гораздо больше

7 голосов
/ 09 апреля 2011

Это относится даже к приложению MainMenu.xib?

Нет, перо MainMenu принадлежит NSApplication (вот кто его загружает).

Должно ли это также относиться к NSWC для окна MainMenu.xib, даже если оно открывается при запуске?

Нет, NSApplication загружает основной кончик на основе свойства NSMainNibFile файла приложения. (Так получилось, что в шаблонах проектов XCode предварительно установлено значение «MainMenu».) Если вы хотите изменить его имя, измените его там (и переименуйте файл nib). (Кстати: это свойство также можно изменить в представлении «Сводка» вашей цели в Xcode 4.)

Должен ли NSWC окна MainMenu также быть делегатом приложения или это должен быть другой класс?

Владелец пера NSMainNibFile является экземпляром NSApplication, который загружает его и по ассоциации с любым делегатом этого экземпляра. Ни один из них не является подклассом NSWC.

В том же духе, должен ли основной NSWC обрабатывать файлы (перетаскивание / открытие и открытие), или его следует передавать делегату приложения, или это просто вопрос вкуса?

Нет "основного NSWC" (приложение / app-делегат является контроллером для NSMainNibFile).

Все операции перетаскивания выполняются подклассами NSWindow или NSView. Я обычно использую специальный подкласс NSWindow или NSView, который просто передает все методы drag-n-drop делегату. Например:

- (unsigned int) draggingEntered:sender
{
    return [[self delegate] draggingEntered:sender];
}

Таким образом, я могу хранить весь свой код окна / вида вместе в соответствующем контроллере (как определено их владельцем пера). И поскольку определенный код окна / представления находится в контроллере (не подкласс NSWindow / NSView), различные типы NSWindows / NSViews могут использовать одни и те же подклассы drag-n-drop.

...