Search code examples
iosuiviewcontrollerautomatic-ref-countingdealloc

UIViewControllers And ARC


So after much deliberation and a bit of frustration at spending time trying to search for memory management issues i did some research and finally succumbed to changing to ARC. And it was relatively painless. However a new issue has surfaced to do with my UIViewControllers, Pre-arc they all worked as advertised, I pushed them on the stack, they appeared, I popped them off the stack their dealloc method was called and everybody was happy. Changing over to ARC, no dealloc is called, ever. which is unfortunate. So I did some research into the problem, let me list out what i am doing and/or not doing

.firstly, the view i am pushing onto the stack is not explicitly declared strong.

.the delegate the child class has of the parent class is unsafe_unretained, but for covering bases i even commented out setting the delegate to the parent, no joy.

.Turned Off NSzombies as apparently that will cause stuff to stick around in ARC enabled code

.i changed my code, according to brad larsons answer in Memory not released in ios view hierarchy, from this

if (_friendsListVC == nil) 
{
    _friendsListVC = [[FriendsListViewController alloc] initWithNibName:nil bundle:nil];
    _friendsListVC.delegate = self;
}

[self.navigationController pushViewController:_friendsListVC animated:YES]; 

(_friendsListVC is a member variable). To This

 FriendsListViewController *fVC = [[FriendsListViewController alloc] initWithNibName:nil bundle:nil];
 //fVC.delegate = self;
 [self.navigationController pushViewController:fVC animated:YES]; 

again no Joy, the dealloc breakpoint never gets hit, and the thing is i push and pop alot of views in my app, so this will only lead to more memory issues, on top of the ones i changed over to ARC to hopefully fix...

Also note i have a few code blocks in this view as well as some of the others but i don't use self which i also read is self retained so you should weak ref's when it comes to code blocks.

i am le stumped, can anyone elucidate me as to what ARC is doing? or what i am not doing in deference to using ARC? and for future reference should all views you want to push onto the view hierarchy in ARC NOT be instance variables?

thanks in advance.


Solution

  • I figured out what the issue was, but it did not fix the OTHER controllers that were not being dealloc'ed, those were for different reasons entirely. So in the interest of spreading knowledge and alleviating anyone else of this pain I am going to list out the number of things that will possibly cause retain cycles, mostly pertaining to ARC and UIViewControllers and code blocks

    1. Don't have a strong reference to the view you are pushing on.

    2. If the class you are pushing onto the view hierarchy has a delegate of the class calling the push method make it an unsafe_unretained reference, in fact it would be good practice to make all your delegates unsafe_unretained as one of my delegates was a strong as i assumed the ARC converter would do that for me.

    3. Turn off NSZombies. Not permanantly mind you, just for when you need to make sure the dealloc statements are being called when they should.

    4. Do not refer directly to self in code blocks, this causes a retain cycle. If you need to use self, do the following outside the block (and then use weakself)

      __unretained_unsafe className *weakSelf = self;

    5. Beware of static references, I am not certain about this but i had a method which took in two instantiated view controllers and pushed one on top of the other, the references were assigned to two static instances of them within this Class (Don't ask why), After zeroing them after they were used it seemed to fix my problem, i am not sure why.

    6. This is another one I am not certain about but saw it mentioned somewhere once or twice, If you have a code block in a class, try not to use instance variables within that block, again make the variable __unsafe_unretained.

    And that's about it, after checking for most of these and fixing them all my views have their dealloc method called when pushed of every time rather than at some weird arbitrary point. Also to clarify this is just a brief checklist to quickly help anyone facing the same issues, I don't claim to have a full understanding of some of the concepts here, but i recommended you should, as i hope to be in time.