在启用了ARC的Cocoa代码中,我尝试观察Window关闭事件,如下所示。
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]];
}];
我认为这将在关闭后删除对控制器(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]];
}];
为什么第一个代码不起作用?
答案 0 :(得分:3)
我认为保留周期介于observer
数组和块之间。 observer
数组包含实际的观察者对象。只要观察者对象存活,它就会占据块。该块保存observer
数组。
这使ScanViewController
成为副作用。我没有看到ScanViewController
强烈提及观察者的证据。
我相信解决方案是从块末尾的observer
数组中删除观察者。另一个解决方案是不使用数组来保存观察者,只是一个__block id
变量。然后,在块的末尾将该变量设置为nil
。