views:

296

answers:

1

Hi

I just have a quick "best practice" question regarding custom cells in a UITableView. My problem arises when I have build a custom cell in the if(cell == nil) block in the

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

(1) If I build labels and set the text property of these inside the (cell == nil) block; only the cells visible on the screen will have the correct text in them, the rest will just be reused.

(2) Ok, so I try moving the building of the custom cell outside the block. This of course results in my cells getting redrawn over and over again each time a user scrolls… and on top of each other.

(3) I also tried placing the drawing of the custom cell (labels, graphics etc.) inside the (cell == nil) block, but setting the labels.text property after the block. This can't be done as my UILabels then can't be accessed from outside the block they were instantiated in. I could do some crazy for(UILabel *l in cell.contentView.subviews ) but that would require an if statement for each label and probably some tags to identify them with.

(4) I could then declare all my labels before the (cell == nil) block and then just do the instantiation and drawing inside the block and setting the text property after the (cell == nil) block. But as I passed 10 UIlabels this looks and feels really messy, having them spread out like this inside and outside the (cell == nil) block, plus they would be declared each time the table has to "refresh".

The reason I ask is because when using 2-4 labels I have always found a way around it, but this time I need 12 custom UILabels set up and I would like to do it so that I have to redraw the least amount of graphics, as there probably will be a lot of cells.

I have seen examples where people and the Apple docs uses a:

- (void) configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {

But I can't really see how that would help me out:)

Hope someone could point out a "best practice" for these sort of things.

Thank you!

+3  A: 

Your option 3 is the way to go. Create the cell with all its subviews whenever a new cell is required (i.e., in the if (cell == nil) block) and set the contents of your labels after the block.

If you use a custom UITableViewCell subclass, you could declare a property for each label and then access them with cell.myLabelX outside the block. If not, I would use the tag property to make the connection. At cell creation, assign a unique tag to each label:

UILabel *label1 = [[UILabel alloc] initWithFrame:...];
label1.tag = MYLABEL1TAG;
[cell addSubview:label1];
...

Outside the block, retrieve the labels through their tags:

UILabel *label1 = (UILabel *)[cell viewWithTag:MYLABEL1TAG];
label.text = ...

This is also how Apple does it in many places in their sample code (at least that's how they did it when I last looked).

Ole Begemann
Thank You Ole:)This is a bit of a twist to my number 3 :) but it adds really good readability to the code. I did not know about the viewWithTag, I thought the only way was to loop through the views and use switch or if statements to identify the tags.Maybe that is why I didn't see it in Apples code :)Thank you again.
RickiG
Without sacrificing to much readability this can be done:((UILabel *)[cell viewWithTag:TRIP_LABEL]).text = @"My trip to Copenhagen";
RickiG
I know this was ages ago but just like to thank you for this answer. Solved a problem that I was annoying the crap out of me.
Rudiger