Лучший способ подключить NSMenuItems от Interface Builder?

Поэтому я потратил некоторое время на проверку CocoaDev, на чтение документации Cocoa по NSMenuItems и выполнение некоторых тестов в Интерфейсном Разработчике.

В моем приложении у меня есть меню приложения ([NSApp mainMenu]), разработанное в Интерфейсном Разработчике. Я вижу три возможных пути:

  1. Поместите мои ответчики действия в NSApplicationDelegate. Мне это кажется странным, отчасти потому, что он находится далеко в пищевой цепи, отчасти потому, что кажется, что он затянут.

  2. Создайте подпредставление (я), которое будет прослушивать различные сообщения действий NSMenuItem. Это может показаться полезным, но похоже, что для того, чтобы он был в цепочке респондента, могла быть какая-то магия, которую я не мог понять.

  3. Создайте NSObject, который прослушивает определенные элементы меню приложения, поместите его в xib и подключите его. Это кажется мне лучшим решением на данный момент, потому что я могу изолировать вещи, и не зависеть от цепочки респондента, чтобы достигнуть определенного объекта. НО мне интересно, если, когда я довожу свое приложение до достаточного уровня сложности, это может быть проблемой, потому что это узурпирует цепочку респондента, которая существует, возможно, по причине, выходящей за рамки простоты использования.

Извините за длинный вопрос. Есть ли предпочтительный подход? Спасибо!

2 ответа

Решение

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

Если ваше приложение не основано на документе, цепочка респондента для сообщений действия выглядит следующим образом:

  1. Кто ответит первым
  2. Посмотреть иерархию
  3. Окно
  4. Оконный контроллер
  5. Оконный делегат
  6. NSApp
  7. Делегат приложения

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

Стоит отметить, что контроллеры представления (подклассы NSViewController) автоматически не вставляются в цепочку респондента. Я делаю это вручную после добавления соответствующего представления в суперпредставление. Например, в NSViewController подкласс:

NSResponder *nextResponder = [[self view] nextResponder];
[[self view] setNextResponder:self];
[self setNextResponder:nextResponder];

Это вставки self (экземпляр подкласса NSViewController) в цепочке респондента между представлением и следующим респондентом исходного представления.

Обратите внимание, что в вашем третьем подходе нет ничего плохого по сути, а именно в том, чтобы иметь конкретную цель (подмножество) сообщений действий. Цепочка респондента существует, чтобы дать возможность различным объектам обрабатывать сообщения действий, потому что некоторые действия могут зависеть от контекста. Например, действия в меню "Файл" обычно применяются к окну, которое в настоящее время является главным окном, поэтому имеет смысл не указывать конкретную цель и вместо этого использовать цепочку респондента. С другой стороны, действия в меню ApplicationName являются действительно глобальными - им не нужно проходить через цепочку респондента, поэтому вы можете подключить их к определенной цели.

Я обычно просто выставляю IBActions в контроллере приложения (NSApp делегировать) и подключить пункты меню к этим действиям. Это довольно стандартный способ ведения дел. Если у вас много пунктов меню, вы также можете разбить функциональность на один или несколько контроллеров, которые подключены к контроллеру приложения, и связать пункты меню с ними.

Другие вопросы по тегам