当我在视图控制器的-addObserverForName: object: queue: usingBlock:
方法中使用NSNotificationCenter
-viewDidLoad:
时,-dealloc
方法最终未被调用。
(当我删除-addObserverForName: object: queue: usingBlock:
时,再次调用-dealloc
。)
使用-addObserver: selector: name: object:
似乎没有这个问题。我究竟做错了什么? (我的项目是使用ARC。)
以下是我的实施示例,以防我在这里做错了什么:
[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
updateResult = YES;
}];
提前感谢您的帮助。
我尝试添加以下内容(无济于事):
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self isMovingFromParentViewController]) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
答案 0 :(得分:17)
updateResult
是一个实例变量,它可以防止对象被该块保留而取消分配。
换句话说,你有一个保留周期。对象保留块,块保留对象。
您需要创建一个弱或不安全的对该实例的引用及其变量,以便失去该关系。
在通知栏之前添加以下内容:
__unsafe_unretained YouObjectClass *weakSelf = self;
或(如果您使用的是iOS5及以上版本)
__weak YouObjectClass *weakSelf = self;
然后,在该块中,通过新的弱引用引用该对象:
[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
weakSelf.updateResult = YES;
}];
请注意,保留周期本身并不是一件坏事。有时你真的希望它们发生。但是那些是你确定循环将在特定时间后被破坏的情况(例如动画块)。一旦块执行并且从堆栈中移除,循环就会中断。
答案 1 :(得分:6)
这很可能是因为你有一个保留周期。
当您的块隐式保留self时,通常就是这种情况,并且self会以某种方式保留块。你将有一个保留周期,因为每个人保留另一个保留周期,因此他们的retainCount永远不会达到零。
您应该激活警告-Warc-retain-cycles
,警告您这些问题。
因此,在您的情况下,您使用变量updateResult
,我假设它是一个实例变量,并且隐式保留self
。您应该使用临时弱变量来表示self,并在块中使用它,这样它就不会被保留并且会中断保留周期。
__block __weak typeof(self) weakSelf = self; // weak reference to self, unretained by the block
[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
// Use weakSelf explicitly to avoid the implicit usage of self and thus the retain cycle
weakSelf->updateResult = YES;
}];
答案 2 :(得分:0)
这不是保留周期。
NSNotificationCenter
按住该区块,区块为self
。因为[NSNotificationCenter defaultCenter]
是一个生活在所有应用生命周期中的单身人士,所以它保持self
间接。