1

在启用 ARC 的 Cocoa 代码上,我尝试观察如下所示的窗口关闭事件。

ScanWindowController * c = [[ScanWindowController alloc] initWithWindowNibName:@"ScanWindowController"];
[scanWindowControllers addObject:c];
[c showWindow:nil];

NSMutableArray *observer = [[NSMutableArray alloc] init];
observer[0] = [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
    [scanWindowControllers removeObject:c];
    [[NSNotificationCenter defaultCenter] removeObserver:observer[0]];
}];

我认为这将在关闭 Window 后删除对控制器 (c) 的所有引用。但实际上,这段代码在关闭 Window 后并没有释放 ScanWindowController。如果我像下面这样使用对控制器的弱引用进行编写,则会调用 ScanWindowController 的 dealloc。

ScanWindowController * c = [[ScanWindowController alloc] initWithWindowNibName:@"ScanWindowController"];
[scanWindowControllers addObject:c];
[c showWindow:nil];

__weak ScanWindowController * weak_c = c;
NSMutableArray *observer = [[NSMutableArray alloc] init];
observer[0] = [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillCloseNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
    [scanWindowControllers removeObject:weak_c];
    [[NSNotificationCenter defaultCenter] removeObserver:observer[0]];
}]; 

为什么第一个代码不起作用?

4

1 回答 1

3

我认为保留周期在observer数组和块之间。该observer数组包含实际的观察者对象。只要观察者对象还活着,它就持有该块。该块包含observer数组。

这保留了ScanViewController副作用。我没有看到任何证据表明ScanViewController它对观察者有很强的参考意义。

observer我相信解决方案是从块末尾的数组中删除观察者。另一种解决方案是不使用数组来保存观察者,而只是一个__block id变量。然后,将该变量设置nil为块的末尾。

于 2013-08-31T02:14:12.507 回答