我有一个奇怪的案例涉及ARC,NSNotificationCenter和一个块。以下是代码的简化示例。从测试来看,似乎didSaveObserver
的内存管理正在按预期执行,即它没有创建保留周期,并且在nil
之前没有removeObserver:
。
然而,我对ARC的理解让我觉得这只是一个侥幸/怪癖,而ARC可以在nil
之前didSaveObserver
removeObserver:
。从未保留didSaveObserver
(唯一的分配是weak
变量),然后ARC可以/(应该)立即解除它。
我是否正确理解了ARC规则?如果是,那么我如何确保didSaveObserver
被保留以便可以不被观察但不创建保留周期?
self.willSaveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextWillSaveNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
id preSaveState = ...; //Store some interesting state about a Core Data object (the details aren't significant to this question).
__weak __block id didSaveObserver = [[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextDidSaveNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
//Unobserve the did save block. This is the tricky bit! didSaveObserver must be __weak to avoid a retain cycle, but doing so also means that the block may be dealloced before it can be unobsered.
[[NSNotificationCenter defaultCenter] removeObserver:didSaveObserver];
id postSaveState = ...;
//Perform work that uses pre & post save states.
}];
}];
更多详情:
如果未添加__weak
(默认为__strong
),仪器会报告保留周期。
答案 0 :(得分:0)
NSNotification.h中有一条评论解释了为什么didSaveObserver
在这种特殊情况下没有被解除分配:
// The return value is retained by the system, and should be held onto by the caller in
// order to remove the observer with removeObserver: later, to stop observation.
当然,这只能解释这个具体案例。
答案 1 :(得分:0)
首先,您认为为什么会创建保留周期?该块将保留didSaveObserver
,是的。 didSaveObserver
会保留该区块吗?除了可以在removeObserver:
中使用以删除添加的观察值之外,没有任何关于返回的观察者对象的文档。它可能以某种方式保留块或块本身,在这种情况下它将创建保留周期。如果您想要安全,是的,您可以使用weak
来引用块中的观察者。
从未保留过看到didSaveObserver(唯一的任务是 一个弱变量),然后ARC可以/(应该)立即解除它。
除非通知中心在返回给您之前保留它。