Take the 2-minute tour ×

I'm a bit confused. I'm subclassing a UITableViewCell to create my own design of a cell. In the -initWithStyle: method I'm setting up some UILabels like so:

self.careerTitleLabel = [[UILabel alloc] init];
[self.contentView addSubview:careerTitleLabel];
[self.careerTitleLabel release];

Then to position the label I do this in -layoutSubviews like so:

CGRect careerTitleLabelFrame = CGRectMake(10, 10, 280, 20);

self.careerTitleLabel.frame = careerTitleLabelFrame;

This code actually works. It positions my label where I want it to be positioned. But what I don't understand is HOW this works. As I'm just modifying the frame of the careerTitleLabel ivar and not the careerTitleLabel that has been added as a subView to the contentView.

My assumption would be that to modify the frame of the label that I had added to the contentView I would have to pull it out by using -viewWithTag: and then modify that frame. Right now I'm merely modifying an ivar of the class?

P.S Another cliffhanger not related to this question is why does self.careerTitleLabel have a retainCount of 2 after being released? D.S

share|improve this question
I get the feeling you need to learn the fundamentals of pointers. The careerTitleLabel ivar is a pointer to the label. The same label you added as a subview. Your code also has some very incorrect memory management. –  Mike Weller Sep 29 '11 at 15:02
add comment

2 Answers

up vote 3 down vote accepted

addSubview: doesn't copy the view you pass it, it retains it. So when you release it, it isn't actually deallocated. It's kept alive because self.contentView is still using it. That means that your reference to self.careerTitleLabel later on still works, though I think most would consider it bad style on the grounds that you should keep owning references to any objects you intend to message later rather than imputing knowledge from ownership patterns used elsewhere.

retainCount is never to be relied on absolutely. It's also opaque how much addSubview: will increase the retain count by, other than that it'll be at least 1. That said, the most likely reason if you've declared careerTitleLabel as a property and have a line like:

NSLog(@"%d", [self.careerTitleLabel retainCount]);

Is that the standard getter is:

return [[careerTitleLabel retain] autorelease];

So the retain count is temporarily increased by the getter, the reasoning being that the results of getters should live at least as long as the autorelease pool — even if the object from which you got them is deallocated before then.

share|improve this answer
So the proper way is: UILabel *tmpTitleLabel = [[UILabel alloc] init]; self.titleLabel = tmpTitleLabel; [myContentView addSubview:titleLabel]; [tmpTitleLabel release]; or even self.titleLabel = [[[UILabel alloc] init] autorelease] ? –  Peter Warbo Sep 30 '11 at 14:06
Assuming you have a retain then either of those is good style and will give you an owning reference, yes. Just don't forget to release it later (for which I usually prefer self.titleLabel = nil;, which both releases it and ensures you don't end up with a dangling pointer). Public commits to LLVM, the compiler Apple use, suggest there'll be a self-zeroing weak pointer in iOS 5, which will be another option if you want logically to say "I want to be able to talk to this, but only while someone else needs it to be alive; I'm not bothered after that". –  Tommy Sep 30 '11 at 14:24
add comment

careerTitleLabel is a pointer to an object. So when you do addSubview: careerTitleLabel, the code you call maintains a reference to careerTitleLabel.

Later, when you set the frame on careerTitleLabel in layoutSubviews, you are updating that same object.

layoutSubviews is absolutely the right place to do this. It's called automatically at the start, and again if the view bounds change. For example if the device's orientation changes.

viewWithTag is another way to access a subview. Personally I consider it cleaner to maintain an ivar. Don't forget you can use IBOutlets to hook up these things using Interface Builder.

Finally, you do have a memory issue and this explains the retain counts. It's good to run Analyze frequently to pick up these issues, and also profile with Instruments using Leaks. You can even set a flag in your build settings to always run Analyze every time you build.

Anyway here's the issue:

self.careerTitleLabel = [[UILabel alloc] init];

If your property in the .h file is set up like:

@property (nonatomic, retain)

then you will over-retain here. You will retain twice and this will cause memory issues.

Apple guidelines recommend you never call these setters in an init method. At that stage behaviour can be unpredictable as you could be going through a custom setWhatever method whilst your object has not yet completed it's init.

Much safer to just have:

    careerTitleLabel = [[UILabel alloc] init];

Even better, in your .h file prefix this with an "m" for member variable. Then you'll have

    mCareerTitleLabel = [[UILabel alloc] init];

In your synthesize, use:

    synthesize careerTitleLabel = mCareerTitleLabel;

That will mean that from outside - or inside - your code, you can access this as:




I hope this helps! It's a lot to cover!

share|improve this answer
add comment

Your Answer


