0

У меня есть нечетный случай с ARC, NSNotificationCenter и блоком. Ниже приведен упрощенный пример кода. Из тестирования кажется, что управление памятью didSaveObserver выполняется по желанию, то есть оно не создает цикл сохранения, и оно не является nil до removeObserver:.Предотвращение освобождения слабо назначенной переменной без создания цикла сохранения

Однако, мое понимание ARC заставляет меня думать, что это всего лишь случайность/причуда, и ARC может nildidSaveObserver до 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

Существует комментарий в 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

Я думаю, что это создает цикл сохранения, потому что инструменты говорят, что он это делает. Я обновил вопрос. –

Смежные вопросы