0

我有一个涉及ARC,NSNotificationCenter和块的奇怪情况。以下是代码的简单示例。从测试看来,didSaveObserver的存储器管理似乎是按照需要执行的,即它不创建保留周期,并且它在removeObserver:之前不是nil防止弱分配的变量被释放而不创建保留周期

但是,我对ARC的理解让我觉得这只是一种侥幸/怪癖,ARC可以在removeObserver:之前nildidSaveObserver。看到didSaveObserver永远不会被保留(唯一的分配是一个0​​变量),那么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

有一个在NSNotification.h这可以解释为什么didSaveObserver没有在这种特殊情况下dealloced评论:

// 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. 

当然,只有解释这种特定情况下。

0

首先,您为什么认为这会创建一个保留周期?该块将保留didSaveObserver,是的。 didSaveObserver会保留该块吗?除了在removeObserver:中可用于删除添加的观察值之外,没有关于返回的观察者对象的任何记录。它可能以某种方式保留了区块或是区块本身,在这种情况下,它会创建一个保留循环。如果你想要安全,是的,你可以使用weak来引用块中的观察者。

看到,因为didSaveObserver从未保留(唯一的任务是 弱变量),然后ARC可以/(应注意什么?)即刻的dealloc它。

除非在返回给您之前由通知中心保留。

+0

我认为它创建了一个保留周期,因为乐器说它有。我已经更新了这个问题。 – 2013-04-23 11:20:38