Не получаю NSWindowWillCloseNotifications - PullRequest
2 голосов
/ 30 марта 2011

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

Я пробовал следующее, все с тем же поведением (оконный контроллер не уведомляется):

  • Удаление регистрационного кода уведомления AppDelegate, в надежде, что каким-то образом оно «потребляет» уведомление.
  • Изменение метода на контроллере представления на -(void)windowIsClosing:, чтобы оно не совпадало с именем делегата приложения (довольно далеко, но мне пришлось попробовать)
  • Перемещение вызова addObserver:... в ViewController в другое место в коде (чтобы он не вызывался во время инициализации, если это как-то имело значение).
  • Я отменяю регистрацию моего контроллера представления из центра уведомлений во время его dealloc метода, но я гарантировал, что метод dealloc вызывается после закрытия окна, а не во время закрытия.

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

Поэтому, почему мой контроллер не уведомляется о событиях закрытия окна, а мой делегат приложения?

Соответствующий код выглядит следующим образом ... Делегат приложения:

@interface AppDelegate : NSObject <NSApplicationDelegate> {
}
@end

@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(windowClosing:) 
                                                 name:NSWindowWillCloseNotification 
                                               object:nil];
    // other initialization stuff
    [self showWelcomeWindow];
}

- (void)windowClosing:(NSNotification*)aNotification {
    // this method gets called when any window is closing
}
@end

Контроллер:

@interface ViewController : NSObject {
}
@end

@implementation ViewController
- (id)init {
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(windowClosing:)
                                                     name:NSWindowWillCloseNotification
                                                   object:nil];
    }
    return self;
}

- (void)windowClosing:(NSNotification*)aNotification {
    // this method does not called when window is closing
}
@end

Ответы [ 2 ]

6 голосов
/ 31 марта 2011

Отвечая на мой собственный вопрос для потомков, теперь, когда я понял это.

Как указано в документации NSNotificationCenter :

Обязательно вызовите removeObserver: или removeObserver: name: object: перед NotificationObserver или любым объектом, указанным в addObserver: selector: name: object: освобожден.

Объект ViewController прослушивал уведомления для закрывающихся окон (NSWindowWillCloseNotifications) и одного из уведомлений объекта моей модели данных. Поэтому, когда я устанавливал другой объект модели на контроллере, я отменял регистрацию ViewController из прослушивание модельного объекта, который был заменен.

К сожалению, я решил использовать метод removeObserver: (который также убрал объект из уведомлений о событиях закрытия окна), а не более конкретный removeObserver:name:object:, чтобы удалить мой контроллер только из подмножества уведомлений о том, что объект зарегистрировался для. Оглядываясь назад на код, removeObserver был написан до того, как объект контроллера должен был быть уведомлен о событиях, происходящих из чего-либо, кроме модели.

Мораль истории заключается в том, чтобы иметь умственную дисциплину для использования [[NSNotificationCenter defaultCenter] removeObserver:self] только во время вызова dealloc объекта и иным образом отменять регистрацию из очень специфических событий (поскольку вы не можете знать, роуд, на какие уведомления о других событиях будет зарегистрирован и объект).

0 голосов
/ 31 марта 2011

Если вы хотите отслеживать недавно использованные документы, вы можете создать подкласс NSDocumentController и внедрить -noteNewRecentDocumentURL:;Затем Cocoa сообщит вам, когда обновит тот же список, который входит в File> Open Recent.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...