views:

262

answers:

4

Hi, I'm using the iPhone SDK 3.0, but I think this is a general misunderstanding of how things work w/ c & memory management.

I've overridden the viewWillAppear method like this

@implementation MyViewController
- (void)viewWillAppear:(BOOL)animated {
  NSArray *items = [NSArray arrayWithOjbects:self.searchButton, self.trashCan, nil];
  [self.bottomBar setItems:items animated:YES];
}
// other stuff...
@end

when I try to switch away from the view controller above and switch back everything works properly.

BUT, my inclination is to "release" the original pointer to "items" because I think a reference to the NSArray is now held by bottomBar. But when I do this (see code below) and try to switch away from the UIViewController, I get a memory management error (-[CFArray count]: message sent to deallocated instance 0xd5f530).

- (void)viewWillAppear:(BOOL)animated {
  NSArray *items = [NSArray arrayWithOjbects:self.searchButton, self.trashCan, nil];
  [self.bottomBar setItems:items animated:YES];
  [items release];
}

Do I need to not release items in this case? Or am I doing something wrong? Obviously, the empirical evidence indicates that I shouldn't release "items", but it's not clear to me why this is the case.

Thanks for any info/"pointers"!

+3  A: 

You do not need to release it because you never init'd it. [NSArray arrayWithObjects:...] returns an autoreleased object. You are not responsible to release it, because it has had the autorelease message sent to it when it returned from the method. You only have to release what you init! (If you had used [[NSArray alloc] initWithObjects:...] you would have had to.)

micmoo
It is true you are not responsible for releasing it, but there is no guarentee it is an autoreleased object. All you know is you don't own it. Read the rules at <http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html>.
Peter N Lewis
A: 

When you call arrayWithObjects: on NSArray:

NSArray *items = [NSArray arrayWithObjects:self.searchButton, self.trashCan, nil];

You are returned an autoreleased array. The array is returned to you autoreleased, because you do not call alloc, new, or a method containing copy on it. This signifies that you do not need to memory manage that object. (Take a look at the Memory Management Programming Guide for Cocoa for more information)

However, it is then retained when you call setItems on self.bottomBar, passing the array as an argument, bumping its retain count up to 1, but then you release it, returning its retain count back to zero, which causes it to be deallocated.

Since the array is retained by self.bottomBar, this implies that it is managing the memory of the array. When it is no longer needed, the array will be released, implying that the class no longer needs the array, which is the correct way to manage the memory.

Perspx
It is true you are not responsible for releasing it, but there is no guarentee it is an autoreleased object. All you know is you don't own it. Read the rules at <http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html>
Peter N Lewis
A: 

Here's the short version:

+[NSArray arrayWithObjects:] returns an object that you do not own, so no, you should not release it.

On the other hand, if you had done:

NSArray *items = [[NSArray alloc] initWithObjects:self.searchButton, self.trashCan, nil];

this creates an object with a retain count of 1, so you would need to release it to prevent it from leaking.

Check out the Memory Management Programming Guide for Cocoa for more details.

Mike McMaster
It is true you are not responsible for releasing it, but there is no guarentee it is an autoreleased object. All you know is you don't own it. Read the rules at <http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html>
Peter N Lewis
I'm aware of the distinction, thanks. I was trying to explain in a way a novice to Objective-C would understand, which is why if he wanted to actually learn this topic in-depth, I linked to the very same documentation you pointed me to.
Mike McMaster
I agree that yours was the best of the answers that failed in this way. But if you know of the distinction, don't add confusion to the newbies. Once you start talking about autoreleased objects, they start thinking about retain counts and its all down hill from there. The memory management rules are simple and easy to understand and say nothing about autorelease or retain counts and yet newbies often get confused because the advice they are given talks about these things.
Peter N Lewis
I disagree that it's as big a deal as you seem to think, but fine. I'll edit my answer to be more correct.
Mike McMaster
A: 

For heavens sake guys, just point people to the Memory Management Rules. Don't paraphrase them. Don't say "returns an autoreleased object" (which is not necessarily true, and is irrelevent even when it is true). Just point them to the rules.

The rules are a sum total of 9 paragraphs! There is no need to paraphrase them, abrieviate them, or restate them. They are clear and concise and explicit.

Read the rules, follow the rules, and you will have no memory management problems.

Peter N Lewis