Отслеживание NSWindow

Я хотел бы отслеживать каждый раз, когда определенное окно появляется (становится видимым для пользователя) в приложении OS X. Где было бы наиболее адекватным местом для вызова трекера?

windowWillLoad, возможно?

Я ожидал найти что-то вроде windowWillAppear, но, похоже, я слишком много думаю об iOS.


person hpique    schedule 20.08.2012    source источник
comment
Что вы имеете в виду под показанным? Как окно появляется и исчезает из поля зрения — скрытие, закрытие, загрузка, makeKey, makeMain? Есть довольно много вариантов, и то, какие из них используются, повлияет на ответ на этот вопрос.   -  person rdelmar    schedule 21.08.2012
comment
В целях отслеживания я бы определил, что показано как становится видимым для пользователя. makeMain не подходит, так как не все окна могут быть главными.   -  person hpique    schedule 21.08.2012


Ответы (2)


Как насчет получения уведомлений, таких как NSWindowDidBecomeMainNotification, по основному, я думаю, тот, который находится на самом верху экрана, который непосредственно виден пользователю.

см.: документацию Apple

person TeaCupApp    schedule 20.08.2012
comment
NSWindowDidBecomeMainNotification не вызывается для панелей, которые также являются окнами. Попробую с NSWindowDidBecomeKeyNotification... - person hpique; 20.08.2012

Да, можно было бы ожидать, что окно уведомит своего делегата или свой контроллер с помощью сообщения windowWillAppear или windowDidAppear или опубликует документированное уведомление, например NSWindowDidAppearNotification. Но увы, таких нет. Я подал отчет об ошибке в Apple, и мне посоветовали вместо этого использовать раскадровку и контроллер представления. Это бесполезно в устаревших приложениях, которые уже используют кучу оконных контроллеров и xib.

Вы можете создать подкласс NSWindow и переопределить orderWindow:relativeTo: для отправки уведомления. Большинство, но не все сообщения, из которых открывается окно, в конечном итоге проходят через этот метод, включая orderBack:, orderFront:, makeKeyAndOrderFront: и -[NSWindowController showWindow:]. Но orderFrontRegardless не проходит через orderWindow:relativeTo:, поэтому для полноты вы также можете переопределить это.

Еще один способ получать уведомления — создать подкласс NSViewController, управляющий некоторым представлением, которое всегда отображается в окне. Контроллер представления получит viewWillAppear и viewDidAppear.

Если вы уже создаете подклассы NSWindow или NSViewController по какой-то другой причине, любое из этих решений является разумным решением.

Если вы еще не создаете подкласс NSWindow и у вас нет подкласса NSViewController для представления, которое всегда отображается в окне, то другим способом является использование привязок Cocoa для подключения привязки окна visible к свойству одного из ваших объектов. Например, у меня есть собственный подкласс NSWindowController. Я дал ему свойство windowIsVisible:

@interface MyWindowController ()

@property (nonatomic) BOOL windowIsVisible;

@end

и я реализовал аксессоры следующим образом:

- (BOOL)windowIsVisible { return self.window.visible; }

- (void)setWindowIsVisible:(BOOL)windowIsVisible {
    NSLog(@"window %@ became %s", self.window, windowIsVisible ? "visible" : "hidden");
}

а в awakeFromNib я привязываю привязку окна visible к свойству следующим образом:

- (void)awakeFromNib {
    [super awakeFromNib];

    [self.window bind:NSVisibleBinding toObject:self withKeyPath:NSStringFromSelector(@selector(windowIsVisible)) options:nil];
}

Когда окно становится видимым, вызывается сеттер setWindowIsVisible: с аргументом YES. Обратите внимание, что если все приложение скрыто и появляется снова, метод установки вызывается снова, даже если он не был вызван с аргументом NO, когда приложение было скрыто. Поэтому будьте осторожны, чтобы не предположить, что окно ранее было скрыто.

Кроме того, привязка может создать цикл сохранения, поэтому вам, вероятно, следует отвязать ее, когда окно закрыто, если только вы не хотите сохранить окно и контроллер. Обратите внимание, что окно действительно публикует NSWindowWillCloseNotification, когда оно закрывается, поэтому вам не нужна какая-то особая магия, чтобы обнаружить это.

person rob mayoff    schedule 31.07.2017