Подтвердить что ты не робот

NSWindowController разъяснение понимания

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

  • Подкласс NSWindowController (NSWC) существует (концептуально) под каждым окном, действуя как клей между элементами пользовательского интерфейса и объектами модели, которыми они управляют/представляют. В принципе, каждое окно в вашем приложении должно иметь свой собственный подкласс NSWC.
  • Владелец файла ниба всегда должен быть подклассом NSWC. Это дело даже для приложения MainMenu.xib?
  • Свойство NSWC window всегда должно быть связано с NSWindow в InterfaceBuilder.
  • Вы должны переопределить метод init, используя [super initWithWindowNibName:], так что, когда вы обратитесь к [mycontroller window], он загрузит nib. Если это также относится к 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, поэтому любые дополнения (в виде передового опыта, опыта, gotchas) будут высоко оценены.

Спасибо, Laurie

4b9b3361

Ответ 1

Что такое окна-контроллеры на самом деле?

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

Конечно, они также являются контроллерами в смысле Model/View/Controller, поэтому они являются подходящим местом для подключения представлений из окна к объектам модели. Для этого им часто приходится выступать в роли делегата или источника данных для объекта вида. Таким образом, вы получили эту часть совершенно правильно.

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

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

WindowControllers и MainMenu.xib

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

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

Надеюсь, это поможет. Вероятно, есть еще много чего сказать о контроллерах окон.

Ответ 2

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

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

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

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

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

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

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

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

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

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

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