addObserverForName and removing observer

蹲街弑〆低调 提交于 2019-12-13 02:22:42

问题


On Cocoa code with ARC enabled, I tried to observe Window closing events like below.

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]];
}];

I thought this will remove all the references to the controller (c) after closing Window. But actually, this code does not dealloc ScanWindowController after closing Window. If I wrote like below using weak reference to the controller, dealloc of ScanWindowController is called.

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]];
}]; 

Why does the first code not work?


回答1:


I think the retain cycle is between the observer array and the block. The observer array holds the actual observer object. So long as the observer object is alive, it holds the block. The block holds the observer array.

This keeps the ScanViewController as a side effect. I see no evidence that the ScanViewController holds a strong reference to the observer.

I believe the solution is to remove the observer from the observer array at the end of the block. Another solution would be to not use an array to hold the observer, just a __block id variable. Then, set that variable to nil at the end of the block.



来源:https://stackoverflow.com/questions/18540946/addobserverforname-and-removing-observer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!