Why is "retain" necessary?


#1

On the bottom of page 101 when we get the available voices from the speech synthesizer, we retain the returned array as follows:

voiceList = [[NSSpeechSynthesizer availableVoices] retain];

I thought I understood Objective-C reference counting pretty well, but I must confess I don’t understand why the retain is necessary. I tried the code without it, and, sure enough, it didn’t work. Why is retain needed? Doesn’t the array returned by NSSpeechSynthesizer availableVoices already have its retain count set to 1?


#2

[quote=“swehba”]On the bottom of page 101 when we get the available voices from the speech synthesizer, we retain the returned array as follows:

I thought I understood Objective-C reference counting pretty well, but I must confess I don’t understand why the retain is necessary. I tried the code without it, and, sure enough, it didn’t work. Why is retain needed? Doesn’t the array returned by NSSpeechSynthesizer availableVoices already have its retain count set to 1?[/quote]

The way I understand it is that yes, it’s retain count is set to 1 when availableVoices is sent to NSSpeechSynthesizer, however, because this was called inside the init method, when init ends, it gets released. Think of it like variable scope, once the method in which it is called ends, the variable is released from memory too.

Since we want voiceList to hold on to that value, it must retain it.


#3

What is “magical” about the init method? Also, we’re assigning the array to an instance variable, not to a variable that’s local to the method.

In thinking about it a bit further, I guess I would explain the need for “retain” like this: We’re receiving an array (actually a pointer to an array) from an object (in this case, a class) without any guarantee as to how long the actual object may exist. By calling “retain” we ensure that the array sticks around until we’re done with it.

Does that make sense?


#4

Yep, that makes sense. That’s kinda how I was trying to explain it. I guess my explanations aren’t always that clear.


#5

To shed some more light on this, what do you guys think about Chapter 4, Memory Management, Page 73:

Rules Concerning Release:

  • If you get an object by any other method (i.e. not alloc, new, copy or muteableCopy), assume that it has a retain count of 1 and is in the autorelease pool.

Sadly, we can’t look at the actual source, but I’m pretty sure the returned availableVoices-array is in the autorelease pool and thus needs to be retained.


#6

Well, the plot thickens – and my confusion deepens. I logged the retainCount on voices immediately after getting them from the synthesizer, and, as I expected the retainCount is 1. That’s without doing a retain. So, now I really don’t understand why we have to do a retain.


#7

To bring this to an end, let me continue my quote from the book:

“If you do not wish it to be deallocated with the current autorelease pool, you must retain it.”

In case you wonder when the availableVoices gets autoreleased if you don’t retain it, take a look at developer.apple.com/mac/library/ … Pools.html

HTH