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