1

I am new to Objective-C and still don't completely grasp the memory management. I have an NSMutableArray of pointers...

NSMutableArray *itemArray;

throughout my program, I add items to it.

//start loop    
MyItem *x = [[MyItem alloc] init];
[itemArray addObject:x];
//end loop

There comes a point when I want to toss all items in the array and re-populate it. Do I just loop through the whole array and send a release message to every object in the array as my intuition tells me, and then removeAllObjects, or does removeAllObjects take care of decrementing all the reference counts? Is the following correct?

//start loop
[[itemArray objectAtIndex:i] release];
//end loop
[itemArray removeAllObjects];

3 Answers 3

5

The real problem you have is this:

//start loop    
MyItem *x = [[MyItem alloc] init];
[itemArray addObject:x];
//end loop

You're allocating an object (so you have ownership), then sticking it in the array and never releasing it. You should do this:

//start loop    
MyItem *x = [[MyItem alloc] init];
[itemArray addObject:x];
[x release];
//end loop

or this:

//start loop    
MyItem *x = [[[MyItem alloc] init] autorelease];
[itemArray addObject:x];
//end loop

Once you add it to the array, the array will take ownership by retaining the object, so you don't have to keep it retained yourself. And when you call -removeAllObjects, the array will release them as appropriate. Basically, once you hand it off to the array, you don't have to worry about it.

<Obligatory ARC plug>

You should start getting used to using ARC, where you won't have to worry about releasing the object at all, because the compiler will do it for you.

Sign up to request clarification or add additional context in comments.

5 Comments

ARC is only part of the iOS SDK at the moment. If you're a Mac developer, that won't be an option.
so, in short, if you alloc/copy/retain, you have to release at some point before the pointer you used to alloc/copy/retain goes out of scope... and the rest is magic? (yes, I'll be sure to read the ARC guide you link to for the long answer)
@Dmitri: yes. Basically, if you use alloc, copy, mutableCopy, retain, or new, you will have to release or autorelease at some point. (Until you start using ARC.) I also suggest reading the Memory Management Programming Guide, which will explain this further.
@jtbandes: I'm pretty sure you're talking about something unrelated to what I said. iOS devs can use it on OS X, but Xcode 4.2 (which introduces the ARC compiler) is being withheld from Mac devs until September.
@Chuck: Ah, that's unfortunate. Well, at least clang's ARC documentation is public.
2

Just call -removeAllObjects. Objects added to an NSArray are retained by the array and released when they are removed.

Note that if you create an object with +alloc you must also release it somewhere with a matching -release or -autorelease. It appears that you don't have one when you are creating your objects. Either:

MyItem *x = [[[MyItem alloc] init] autorelease];
[itemArray addObject:x];

or

MyItem *x = [[MyItem alloc] init];
[itemArray addObject:x];
[x release];

will work.

5 Comments

So... does that mean any time a pointer to an object is allocated, the reference count goes up, and any time the pointer gets de-allocated the ref count is decremented? For example, if I have a pointer local to a function, the ref count for that object goes up until the function returns and the pointer is popped off the stack? I was brought up as a C coder, so I find it hard to believe in this kind of magic.
No, it's more manual than that, and the rules are conventions, not magic. The reference count is incremented when -retain is called and is decremented when -release or -autorelease are called. Simply assigning an object to a pointer has no impact on the reference count. By convention, methods with names that begin with "new", "alloc", or "copy" return objects that have already had their reference counts incremented for you, meaning that you are obligated to balance those method calls with matching releases.
Other methods that return objects will typically return an object that has already been both retained and autoreleased, so it will survive until the end of the current runloop, and you need not worry about releasing it. If you want to keep an object like that around, you will have to retain it.
Note that Apple has introduced a new feature with Lion and XCode 4.1, Automatic Reference Counting (or ARC), whereby the compiler takes care of inserting retains and releases for you, which makes the code look and behave like exactly the magic I just told you doesn't exist. :)
Oh. so the addObject function is the thing that's retaining... so getting used to this must be a matter of trusting the API writers and reading the docs for the functions you're using and knowing their conventions...
1

The 'add' group of methods on NSArrays retain the objects you pass in, and the remove 'group' of methods release them, so you are ok using your second method. Your first method actually (sending release to each object then calling removeAllObjects), will most likely result in a BAD_EXEC_ACCESS exception being thrown.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.