View a dealloc controller not called when using the NSNotificationCenter block code method with ARC

When I use -addObserverForName: object: queue: usingBlock: for NSNotificationCenter in the -viewDidLoad: method of my view controller, the -dealloc method -dealloc not called.

(When I -addObserverForName: object: queue: usingBlock: -dealloc is called again.)

Using -addObserver: selector: name: object: doesn't seem to have this problem. What am I doing wrong? (My project uses ARC.)

Below is an example of my implementation if I am doing something wrong:

 [[NSNotificationCenter defaultCenter] addObserverForName:@"Update result" object:nil queue:nil usingBlock:^(NSNotification *note) { updateResult = YES; }]; 

Thanks in advance for your help.

I tried to add the following (to no avail):

 - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; if ([self isMovingFromParentViewController]) { [[NSNotificationCenter defaultCenter] removeObserver:self]; } } 
+8
ios iphone uiviewcontroller nsnotificationcenter dealloc
source share
3 answers

updateResult is an instance variable that prevents an object from being freed because it is saved by this block.

In other words, you have a retention cycle. The object saves the block, and the block saves the object.

You will need to create a weak or insecure link to this instance and its variable to lose this relationship.

Add the following before the notification block:

 __unsafe_unretained YouObjectClass *weakSelf = self; 

or (in case you are on iOS5 and above)

 __weak YouObjectClass *weakSelf = self; 

Then, within this block, reference the object through this new weak link:

 [[NSNotificationCenter defaultCenter] addObserverForName:@"Update result"                         object:nil                          queue:nil                       usingBlock:^(NSNotification *note) {                         weakSelf.updateResult = YES;                       }]; 

Note that save cycles are not a bad thing in itself. Sometimes you really want them to happen. But these are cases when you are sure that the cycle will be broken after a certain time (for example, Animation blocks). The cycle is interrupted after block execution and is removed from the stack.

+17
source share

This is very likely because you have a save cycle.

This, as a rule, is the case when your block implicitly holds itself, and itself saves the block in some way. You will have a hold cycle, as each one saves the other, and their keepCount will thus never reach zero.

You should activate the -Warc-retain-cycles warning, which will warn you of such problems.

So, in your case, you are using the updateResult variable, which I assume is an instance variable, and this implicitly saves self . Instead, you should use a temporary weak variable to represent yourself and use it in your block so that it does not persist and you interrupt the save cycle.

 __block __weak typeof(self) weakSelf = self; // weak reference to self, unretained by the block [[NSNotificationCenter defaultCenter] addObserverForName:@"Update result" object:nil queue:nil usingBlock:^(NSNotification *note) { // Use weakSelf explicitly to avoid the implicit usage of self and thus the retain cycle weakSelf->updateResult = YES; }]; 
+6
source share

This is not a conservation cycle.

NSNotificationCenter hold block, block hold self . Since [NSNotificationCenter defaultCenter] is singleton, living throughout the entire application life cycle, it therefore keeps self indirect.

0
source share

All Articles