7

I know memory management in iOS is tricky subject to newbies like me, but I was hoping for a clear explanation here on stackoverflow which I could not find anywhere else.

So, pretend I have a property / ivar

@property(nonatomic, retain) UIPopoverController *popOver;

which I'm allocating like this:

self.popOver = [[[UIPopoverController alloc] initWithContentViewController:popOverContent] autorelease];    

Now, in my dealloc and viewDidUnload methods, I do both

// in viewDidUnload:
self.popOver = nil;
// in dealloc:
[popOver release];

Question:

  1. If I do nil / release in viewDidUnload / dealloc, do I really need to autorelease at allocation?
  2. Vice versa, if I do autorelease at allocation, do I need to nil / release later?
  3. What's the difference, if any?

Thanks in advance for your time - I'll continue reading, seriously memory management can't be that hard to wrap your head around...

EmptyStack
  • 50,606
  • 20
  • 144
  • 175
pille
  • 1,381
  • 1
  • 13
  • 18
  • Thanks for editing the title; I saw similar questions which had the "iOS:" in front; actually started without it. – pille Sep 03 '11 at 14:24

3 Answers3

5

1 If I do nil / release in viewDidUnload / dealloc, do I really need to autorelease at allocation?

Yes.

2 Vice versa, if I do autorelease at allocation, do I need to nil / release later?

Yes.

In the first case, the auto-releasing is done on behalf of that method. That method doesn't need the popover anymore, so it needs to (auto)release it.

At dealloc, your object doesn't need the popover anymore. Therefore, you need to release it.

It's very simple. You don't have to consider long-term object ownership; you just need to think very locally, at the level of every method. The decision of releasing it or not doesn't at all depend on whether that object is kept by some other parts of the program. In a method, if you alloc an object and you no longer need it in that method, you (auto)release it.

The dealloc is a slight exception to the rule. There, you need to release the ownership of all the instance variables.

That's it!

Yuji
  • 33,649
  • 3
  • 65
  • 85
5

Don't be confused by the autorelease in this line:

self.popOver = [[[UIPopoverController alloc] initWithContentViewController:popOverContent] autorelease];

After this statement you effectively own the object because the property setter claimed ownership of it. The autorelease balances the alloc-init.

So... yes, you need to autorelease at allocation. If you did this (no autorelease), you would leak:

self.popOver = [[UIPopoverController alloc] initWithContentViewController:popOverContent];

Another option is to use a temporary variable instead of autorelease:

UIPopoverController *temp = [[UIPopoverController alloc] initWithContentViewController:popOverContent];
self.popOver = temp;
[temp release];

Either way you need to release the object in dealloc.

Anton
  • 4,484
  • 2
  • 35
  • 58
albertamg
  • 28,172
  • 6
  • 61
  • 70
  • Thanks to Abizern & Yuji as well for their very enlightening answers. Also now I understood the idea of "local ownership" as described in Yuji's answer. Anyhow, is there any way to test your application for memory leaks (maybe using Instruments)? – pille Sep 03 '11 at 14:30
  • @pille Yes, you can use [Instruments](http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/Introduction/Introduction.html). In Xcode, [click and hold the run button](http://stackoverflow.com/questions/5305906/xcode-4-running-the-leaks-instrument) or select [Product -> Profile](http://stackoverflow.com/questions/5304390/instruments-in-xcode-4). This brings up a dialog where you can choose "Leaks". – albertamg Sep 03 '11 at 15:19
  • @pille Even before using Instruments, just do "Analyze", which is available below "Build" menu of XCode. – Yuji Sep 04 '11 at 08:42
1
  1. Yes. But maybe not in this case.
  2. Yes. But maybe not in this case.
  3. viewDidUnload is called when the the view is unloaded, dealloc is called when the view Controller is being destroyed.

In viewDidUnload you release objects that are used by the view that are not needed anymore and can be recreated in viewDidLoad. Obvious, since the view is not being displayed it doesn't need to hold on to the objects that are set up by the view controller for it.

In dealloc you are cleaning up the viewController and here you clear up all it's resources, including those that it has assigned to the view.

In this case, the view does not own the popover controller - it should be owned by the view controller, so there is no need to release it in viewDidUnload but you do need to release it in the dealloc.

Abizern
  • 129,329
  • 36
  • 198
  • 252