2015-10-20 3 views
0

У меня есть одно окно с кнопкой в ​​нем. Когда я нажимаю на кнопку, он открывает другое окно (оба окна находятся в одном файле xib). Я сделал это, привязав кнопку в первом окне к orderFront второго окна. Это работает так, как ожидалось. Теперь мне нужна функция обратного вызова (IBAction), чтобы активировать ее, когда появляется второе окно (чтобы внести некоторые изменения во второе окно на основе настроек в первом окне). У меня есть экземпляр IBAction во втором классе контроллера окна, но я не могу найти триггер, чтобы окно стало видимым для привязки к нему. Странно, что нет ничего о функциях обратного вызова, которые станут видимыми для NSWindow в любом месте (поиск в Google). Этот материал выполняется с помощью кликов в .NET и Visual Studio (я переношу код из .NET). Неужели я об этом совершенно неправильно или что-то в этом роде?IBAction для окна, видимого в какао для OS X

ответ

1

Я бы сказал, что да, с точки зрения стандартного дизайна какао, вы пытаетесь сделать это немного неправильно, по двум причинам. Извините за длинный ответ, есть много, чтобы пойти здесь на концептуальном уровне.

Прежде всего, если вы хотите знать, что определенные вещи произошли с конкретными объектами, механизм цели/действия не является стандартным способом для этого в Cocoa, если только «происходящее» не является прямым действием пользователя, таким как щелчки. Способ, которым вы подключили действие кнопки, чтобы показать окно, в порядке; который инициируется пользователем (нажатие кнопки), и поэтому действие является подходящим. Но чтобы узнать, что второе окно изменило состояние (стало видимым), было бы более типичным использовать либо (1) делегирование, либо (2) уведомления. Оба они полезны; прочитайте их в документах Apple (я уверен, что Google поможет вам здесь). Например, вы можете объявить объект делегатом вашего второго окна и затем получать сообщения, когда окно становится ключевым или основным, когда оно меняет экраны, когда оно закрывается, и т. Д. - какие бы изменения в состоянии вас не интересовали .

Однако здесь есть второй поворот. Если вы посмотрите на документы для протокола NSWindowDelegate, вы увидите методы делегирования таких вещей, как windowShouldClose: и windowWillClose:, но нет соответствующего метода, например windowDidOpen: или windowDidOrderIn:. Есть некоторые методы делегатов, которые могут сработать для вас, в зависимости от того, что вы делаете, например windowDidBecomeKey: или windowDidBecomeMain:, или, может быть, даже windowDidExpose:, но нет windowDidOpen: или аналогичных. Это, я думаю, Apple отправляет вам сообщение: ваш код действительно не должен заботиться. Поэтому вы не должны использовать windowDidBecomeKey: и т. Д., Если они действительно не представляют интересующее вас событие - и похоже, что нет. Вместо этого вы должны глубже подумать о том, что Apple говорит вам, не включая сообщение windowDidOpen:. Почему бы им не оставить такое очевидное сообщение делегата?

Вот мой ответ на этот вопрос. Второе окно уже загружено, так как оно находится в одном и том же столбце, как и в первом окне. Является ли это видимым или нет, в любой момент времени, является деталью, что разумно избегать делать предположения, и именно поэтому я предположил бы, для дизайна делегата Apple. Окно может автоматически отображаться при восстановлении окна; это может прийти и уйти в результате чего-то вне кода вашего приложения, с технологией, например Exposé или Spaces, или тем, что Apple решит сделать дальше; и вы можете сделать окно видимым в разных местах вашего кода. Вам не нужно беспокоиться о таких деталях с кодом, чтобы настроить окно в последнюю минуту, прежде чем станет видимым, чтобы выглядеть правильно. Если окно находится в списке окон, в настоящее время оно видимо или нет, это не должно быть проблемой вашего кода в большинстве случаев; окно должно храниться в хорошем состоянии, так что он будет рад быть показан без необходимости исправления в последнюю минуту незадолго до того, как он станет видимым.Согласно дизайну Apple, ваш код должен быть обеспокоен моментом, когда окно сначала создается из nib, чтобы настроить его в правильном состоянии - для этого - awakeFromNib - и примерно в тот момент, когда окно закрывается (потому что обычно, хотя не всегда, окно перестает существовать, когда оно закрыто, и поэтому необходимо выполнить очистку) - windowWillClose:. Между ними ваше окно должно храниться в хорошем состоянии. Работа над этим должна быть минимальной, поскольку весь чертеж будет подавлен, если только окно не будет на экране.

Итак, когда вы пишете, что хотите «внести некоторые изменения во второе окно на основе настроек в первом окне», правильный дизайн, скорее всего, должен внести эти изменения во второе окно сразу в ответ на любые изменения в появляется первое окно. Обнаружить изменения в первом окне с действиями, связанными с любым пользовательским интерфейсом, и в ответ на эти действия изменить второе окно. Затем, когда отображается второе окно, ваш код даже не нужно знать. Это гораздо более чистый дизайн; это означает, например, что если первое окно изменится после того, как второе окно будет показано, второе окно автоматически отреагирует на эти изменения, тогда как «зафиксировать второе окно до того, как оно появится», дизайн не достигнет этого ,

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

Я хотел бы призвать вас не взломать это на подклассы NSWindow, как предложил другой ответ (этот ответ, теперь удаленный, предложил подклассу и переопределить такой метод, как makeKeyAndOrderFront:, чтобы более или менее взломать функциональность windowDidOpen:). Apple отказалась от сообщения делегата windowDidOpen:; если бы это был просто рассеянный надзор, это было бы добавлено много лет назад. Ключом к программированию в Cocoa является научиться не бороться с Apple. Какао - это очень хорошо разработанная структура, в целом (хотя есть классы, которые являются исключениями: ->), и если вы научитесь идти с ним, а не сражаться, ваша жизнь будет намного проще в конце.

+1

Я удалил свой ответ, вы были правы в этом. – Moritz

+0

Причина, по которой я пытался избежать внесения изменений во второе окно сразу, - это ... combobox в первом окне выбирает * функцию *, которую пользователь может * применить * прямо там и включает в себя тяжелые вычисления. Пользователь также может дополнительно * изменить * * функцию * - во втором окне. Проблема заключается в определении того, как настроить второе окно, также включает сильную синтаксическую разметку строк. Поэтому я просто старался не тратить время на вычисление при настройке второго окна, когда пользователь пытается * применить * функцию и не намерен ее модифицировать. Но на данный момент я просто соглашусь с вашим предложением. – Hashman

+0

Кажется, что вы, возможно, захотите, чтобы второе окно было в отдельном наконечнике, настроенное, когда этот наконечник загружается. – bhaller

Смежные вопросы