/ / Предотвратяване на раздаването на слабо определена променлива, без да се създава задържащ цикъл - какао-докосване, какао, автоматично преброяване, обективни блокове c, нотификация

Предотвратете делаксирането на слабо назначена променлива, без да създавате задържащ цикъл - какао-докосване, какао, автоматично преброяване, обективни блокове c,

Имам един странен случай, включващ ARC, NSNotificationCenter и блок. По-долу е опростен пример за кода. От тестването изглежда, че управлението на паметта на didSaveObserver се изпълнява по желание, т.е. не създава задържащ цикъл и не е nilпреди това removeObserver:.

Въпреки това, моето разбиране за ARC ме кара да мисля, че това е само един fluke / quirk и 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 за отговор № 1

Има коментар в 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.

Разбира се, това обяснява само този конкретен случай.


0 за отговор № 2

Първо, защо мислите, че ще създаде задържащ цикъл? Блокът ще запази didSaveObserver, да. Би се didSaveObserver запази блок? Нищо не е документирано за възстановения обект на наблюдателя, различен от този, в който може да се използва removeObserver: за да премахнете добавяното наблюдение. Възможно е той някак си да задържи блока или да е самият блок, в който случай ще създаде задържащ цикъл. Ако искате да сте в безопасност, да, можете да използвате weak да се позове на наблюдателя в блока.

Виждайки, че didSaveObserver никога не се запазва (единствената задача е да слаба променлива), тогава ARC би могъл / (трябва?) незабавно да го раздели.

Ако не бъде задържан от центъра за уведомяване, преди да се върнете при вас.