[英]View controller dealloc not called when using NSNotificationCenter code block method with ARC
When I use -addObserverForName: object: queue: usingBlock:
for NSNotificationCenter
in the -viewDidLoad:
method of my view controller, the -dealloc
method ends up not being called. 当我在视图控制器的-viewDidLoad:
方法中使用-addObserverForName: object: queue: usingBlock:
for NSNotificationCenter
时, -dealloc
方法最终没有被调用。
(When I remove -addObserverForName: object: queue: usingBlock:
, -dealloc
is called again.) (当我删除-addObserverForName: object: queue: usingBlock:
,再次调用-dealloc
。)
Using -addObserver: selector: name: object:
doesn't seem to have this problem. 使用-addObserver: selector: name: object:
似乎没有这个问题。 What am I doing wrong? 我究竟做错了什么? (My project is using ARC.) (我的项目是使用ARC。)
Below is an example of my implementation, in case I'm doing something wrong here: 下面是我的实现示例,以防我在这里做错了:
[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
updateResult = YES;
}];
Thanks in advance for any help. 在此先感谢您的帮助。
I've tried adding the following (to no avail): 我尝试添加以下内容(无济于事):
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self isMovingFromParentViewController]) {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
}
updateResult
is an instance variable which prevents the object from being deallocated as it is retained by that block. updateResult
是一个实例变量,它可以防止对象被该块保留而取消分配。
In other words, you got a retain cycle. 换句话说,你有一个保留周期。 The object retains the block and the block retains the object. 对象保留块,块保留对象。
You will need to create a weak or unsafe_unretained reference to that instance and its variable for loosing that relationship. 您将需要创建一个弱或不安全的对该实例的引用及其变量以释放该关系。
Add the following prior to your notification block: 在通知块之前添加以下内容:
__unsafe_unretained YouObjectClass *weakSelf = self;
or (in case you are on iOS5 and above) 或者(如果您使用的是iOS5及以上版本)
__weak YouObjectClass *weakSelf = self;
Then, within that block, reference the object via that new weak reference: 然后,在该块中,通过新的弱引用引用该对象:
[[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
weakSelf.updateResult = YES;
}];
Please note that retain-cycles are not a bad thing per se. 请注意,保留周期本身并不是一件坏事。 Sometimes you actually want them to happen. 有时你真的希望它们发生。 But those are instances where you are certain that the cycle will be broken after a specific time (eg Animation Blocks). 但是那些是你确定循环将在特定时间后被破坏的情况(例如动画块)。 The cycle is broken once the block has executed and is removed from the stack. 一旦块执行并且从堆栈中移除,循环就会中断。
This is very likely because you have a retain cycle. 这很可能是因为您有一个保留周期。
This is typically the case when your block implicitly retain self, and self retains the block in a way. 当您的块隐式保留self时,通常就是这种情况,并且self会以某种方式保留块。 You will have a retain cycle as each one retains the other one, and their retainCount thus never reach zero. 你将有一个保留周期,因为每个保留周期,因此他们的retainCount永远不会达到零。
You should activate the warning -Warc-retain-cycles
that will warn you about such issues. 您应该激活警告-Warc-retain-cycles
,它会警告您这些问题。
So in your case, you are using the variable updateResult
, which I assume is an instance variable, and this implicitly retain self
. 所以在你的情况下,你使用变量updateResult
,我假设它是一个实例变量,这隐式保留self
。 You should instead use a temporary weak variable to represent self, and use this in your block, so that it does not get retained and you break the retain cycle. 您应该使用临时弱变量来表示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;
}];
This is not retain cycle. 这不是保留周期。
NSNotificationCenter
hold the block, block is hold self
. NSNotificationCenter
持有块,块self
。 Because [NSNotificationCenter defaultCenter]
is a singleton living in all app life cycle, So it hold self
indirect. 因为[NSNotificationCenter defaultCenter]
是一个生活在所有应用程序生命周期中的单例,所以它保持self
间接。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.