Dealloc not being called on ARC app

rob picture rob · Feb 9, 2012 · Viewed 34.6k times · Source

I have a UIViewController that is pushed onto a container controller and then popped off, and using the allocations instrument, I can see that the view controller is destroyed afterwards. However, a breakpoint in the controller's dealloc is never reached. Does anyone know why dealloc isn't called? Is it possible for ARC to destroy an object without calling dealloc?

Also, I've disabled NSZombies (some have said that can cause dealloc not to fire).

Edit:

Dealloc doesn't do much, just prints to the console, and it never gets called:

- (void)dealloc { NSLog(@"Deallocating..."); }

I can't post the container controller–it's proprietary and too complicated. Dealloc is called consistently on some controllers and not others. If I can find the time I will try and post a simplified version that reproduces the problem.

Is there any way to verify that NSZombies is disabled?

Edit2

I'm posting a screenshot from instruments; it looks to me like it's properly deallocating.

enter image description here

Answer

mikeq picture mikeq · Sep 21, 2012

I just ran across a similar issue. Do you have any blocks where you are referring to 'self'? I had some blocks for notification observation in my init where I was referring to 'self'. Under ARC self is retained in blocks. My dealloc wasn't getting called and that was where I was removing the observation.

The trick is to create a __weak (iOS 5+) or __unsafe_unretained (iOS 4.x) reference to your 'self' and use that to access self or any _iVars (these will cause 'self' to be retained as well) in the block. Here's an example.

__unsafe_unretained TableViewController *weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:NSManagedObjectContextObjectsDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
        if (weakSelf.tableView) {
            [weakSelf.tableView reloadData];
        }
    }];