6

Until five minutes I was sure that my understanding about Objective c reference counting is excellent, but when I started checking objects retainCount I was very surprised to see what I saw.

For example myViewController has a UITableview:

.h file

@interface RegularChatViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
     UITableView *_tableView;
}
@property (nonatomic, retain) IBOutlet UITableView *tableView; 

.m file

@synthesize tableView = _tableView;

- (void)loadView
{
    _tableView = [[UITableView alloc] init];  // STEP ONE
    NSLog(@"tableView retain count: %d",[_tableView retainCount]);

    self.tableView.frame = CGRectMake(0, 0, 320, tableHeight); // STEP TWO
    NSLog(@"tableView retain count: %d",[_tableView retainCount]);  

    [self.view addSubview:self.tableView]; // STEP THREE
    NSLog(@"tableView retain count: %d",[_tableView retainCount]); 
}

To my surprise the input was:

tableView retain count: 1
tableView retain count: 2
tableView retain count: 3

obviously STEP ONE increase retain count by 1 with alloc

I also know that STEP THREE increase retain count by 1 with addSubview

But whats going on in STEP TWO ??? why did it increase the retain count???
is there something to do with ARC??

graver
  • 15,183
  • 4
  • 46
  • 62
Eyal
  • 10,777
  • 18
  • 78
  • 130
  • Maybe because `.frame` cannot exist without the table view and therefore adds the retain count? – Ja͢ck May 22 '12 at 12:03
  • Good guess; but `frame` returns a structure directly; not even a reference. No dependency there. – bbum May 22 '12 at 16:03

5 Answers5

7

According to Apple docs on NSObject Protocol Reference for the retainCount method:

Important This method is typically of no value in debugging memory management issues. Because any number of framework objects may have retained an object in order to hold references to it, while at the same time autorelease pools may be holding any number of deferred releases on an object, it is very unlikely that you can get useful information from this method.

graver
  • 15,183
  • 4
  • 46
  • 62
  • 1
    Indeed. I get really worried when I see developers logging out retain counts in their code. As long as you follow the ownership rules and use the Leaks tool every once in a while, you're golden. – Mike Weller May 22 '12 at 12:03
2

As soon as you interact with any framework method or function whatsoever, the retainCount method becomes completely useless, because you don't know what these things do in their black boxes (they could add your objects to autorelease pools or whatever) and you shouldn't care about it.

Using retainCount to debug memory management issues is always a bad idea. See this answer for even more reasons to avoid it.

Community
  • 1
  • 1
omz
  • 53,243
  • 5
  • 129
  • 141
2

I have a handy guide here: When to use retainCount?

In short, retainCount rarely means what you think it will. Without knowing how UITableView and UIView are implemented you can't know what the retain count should be. And we're not even taking autorelease into account...

Stephen Darlington
  • 51,577
  • 12
  • 107
  • 152
  • That really isn't a helpful web page, and I hate seeing it posted here. One single word with no explanation just gives jollies to the link poster; it doesn't help the asker a bit. – jscs May 22 '12 at 16:30
  • Did you scroll down? Also note that I included all the relevant information in the answer. – Stephen Darlington May 22 '12 at 16:36
  • The answer's fine, of course. I had never scrolled down on the page, no. With the links at the bottom, it's much better than I thought, but I can't be the only one who saw the assumed that there was nothing else there, since you've seem to have set it up so that for most screens none of the bottom content shows initially. – jscs May 22 '12 at 16:45
0

Well in step two :- by using self. tableView, getter of tableview property(which is set retain) will called. So as your property is allocated and retained both so retain count increases respectively.

Whenever you have to allocate a retained property , you should overwrite its getter method and this is called lazy instantiation.

Better allocate your tableview in its getter e.g.

-(UITableView *) tableView
{
     if(!_tableView) {
          _tableView  =  [[UITableView alloc]init];
     }

    return _tableView;
}
Pang
  • 9,564
  • 146
  • 81
  • 122
Deepak
  • 348
  • 4
  • 14
0

self.tableView.frame will retain and autorelease when returning the tableView from the getter.

Sulthan
  • 128,090
  • 22
  • 218
  • 270