0

Looking at Apple's ToolbarSearch example, I see that their view controller's searchBar variable has a retain property and it does this:

searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 400.0, 0.0)];

in the controller's dealloc, the searchBar is released. However, its viewDidUnload doesn't release but just sets the searchBar variable to nil.

I thought the alloc increments the retain count and that the retain property of the variable additionally increments the count. If this is true, wouldn't it mean the searchBar needs to be released in viewDidUnload?

Joey
  • 7,537
  • 12
  • 52
  • 104

2 Answers2

1

Joey -

The 'retain' attribute of a synthesized property only applies when the mutator is called. So, if an external class called:

[viewController setSearchBar:mySearchBar];

The viewController would call retain on mySearchBar. Since

searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 400.0, 0.0)];

doesn't go through the mutator (it just modifies the instance variable searchBar directly), there's only a retain count of one of the object (from alloc).

So, the retain/release count in the example is correct. +1 from alloc, -1 from release in the implementation of dealloc.

If you're confused about the difference between -viewDidUnload and -dealloc, here's a great explanation: What exactly must I do in viewDidUnload?

Community
  • 1
  • 1
Stephen Poletto
  • 3,645
  • 24
  • 24
  • I had thought (evidently incorrectly) that synthesizing the property and setting it to 'retain' meant it would increment the count when you set it to something. Is this when you do self.searchBar = something? I thought the intention was that the synthesis allowed me to use the equals syntax instead of the setVar syntax. – Joey Mar 30 '11 at 23:51
  • @Joey: There's a big difference between searchBar = something and self.searchBar = something. The latter is syntactic shorthand for calling the mutator. It's equivalent to [self setSearchBar:something]; Synthesizing a property just generates the -searchBar and -setSearchBar methods for you. Using 'retain' as an attribute for the property will add a call to retain to the new object when you call the setter. So self.searchBar = something increments the retain count, while searchBar = something does not. – Stephen Poletto Mar 31 '11 at 00:06
1

However, its viewDidUnload doesn't release but just sets the searchBar variable to nil.

That's not true. The -viewDidUnload method you refer to has the line:

self.searchBar = nil;

That is passing nil to the setter for the searchBar property and is equivalent to:

[self setSearchBar:nil];

The setter for a retain property sends release to the old value and retain to the new one.

Jonah
  • 17,918
  • 1
  • 43
  • 70
  • Right, I misspoke, but understand what you mean. My confusion is that I thought alloc-ing and then also setting searchBar equal to the result resulted in two retain count increments, while the setting of the property to nil in viewDidUnload decrements it by one in the way you described above. I *thought* balancing it out would require the alloc to have an autorelease so that there is just the one retain from setting searchBar equal to the alloc'ed search bar. Am I missing something here? Does it have to do with the syntax not being "self.searchBar =" when it's first allocating it? – Joey Mar 31 '11 at 00:01
  • Exactly, as answer by Stephen; `searchBar =` is setting an ivar while `self.searchBar =` is sending a message to a property setter and they do not have the same behavior. – Jonah Mar 31 '11 at 00:11
  • It is precisely to avoid this sort of confusion that it is good practice (in my view) to establish slightly different naming standards for ivars vs properties. If you have a property called 'searchBar', make sure its corresponding ivar is called 'mSearchBar' or something like that. Plus of course you need to make sure you have a "@synthesize searchBar = mSearchBar". Zero confusion this way. – Dev Kanchen Jun 22 '11 at 06:38