【问题标题】:Not receiving NSWindowWillCloseNotifications没有收到 NSWindowWillCloseNotifications
【发布时间】:2011-04-01 01:00:51
【问题描述】:

在我正在创建的应用程序中,我有一个带有最近文档列表的欢迎窗口(功能类似于新 Xcode 4 的欢迎窗口)。我在欢迎窗口中注册了应用程序的委托和视图控制器,用于发布NSWindowWillCloseNotification。不幸的是,只有应用程序委托才会收到此事件的通知。

我尝试了以下所有操作,都具有相同的行为(未通知窗口控制器):

  • 删除 AppDelegate 的通知注册代码,希望它以某种方式“消耗”通知。
  • 将视图控制器上的方法更改为-(void)windowIsClosing:,使其与应用程序委托的名称不同(很远,但我必须尝试)
  • 将 ViewController 中的 addObserver:... 调用移动到代码中的其他位置(因此在初始化过程中不会调用它,如果这很重要的话)。
  • 我确实在通知中心的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

【问题讨论】:

  • 视图控制器在什么时候被初始化?
  • @Sam 欢迎窗口由 NSWindowController 的子类引用,它们之间的关系在 NIB 中设置。该 NSWindowController 对象有一个用于它初始化的 ViewController 的 ivar(我已经验证了 ViewController 的 -(id)init 方法正在被调用)。

标签: objective-c cocoa macos


【解决方案1】:

既然我已经弄清楚了,就为后代回答我自己的问题。

NSNotificationCenter documentation中所述:

确保在 notificationObserver 或 addObserver:selector:name:object: 中指定的任何对象被释放之前调用 removeObserver: 或 removeObserver:name:object:。

ViewController 对象正在侦听正在关闭的窗口的通知 (NSWindowWillCloseNotifications) 和我的数据模型对象的通知之一。因此,当我在控制器上设置不同的模型对象时,我正在取消注册 ViewController监听被替换的模型对象。

不幸的是,我选择使用removeObserver: 方法(该方法也将对象从窗口关闭事件的通知中删除)而不是更具体的removeObserver:name:object: 仅从对象通知的子集中删除我的控制器已注册。回顾代码,removeObserver 是在控制器对象需要通知来自模型以外的任何事件之前编写的。

故事的寓意是在对象的dealloc 调用期间仅使用[[NSNotificationCenter defaultCenter] removeObserver:self] 并在非常具体的事件中取消注册(因为你无法知道下来)道路还有什么其他事件通知对象将被注册)。

【讨论】:

    【解决方案2】:

    如果你想查看最近使用的文档,你可以继承NSDocumentController并实现-noteNewRecentDocumentURL:;然后 Cocoa 会在更新文件 > 打开最近的列表时通知您。

    【讨论】:

      猜你喜欢
      • 2016-08-08
      • 2014-12-17
      • 2016-03-26
      • 2011-06-30
      • 2013-02-24
      • 2011-11-29
      • 2015-06-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多