views:

384

answers:

1

I have a custom UITableViewCell that I created in IB. To populate a UITableView with instances of these cells, loaded from a NIB, I use the following code:

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

    static NSString *CellIdentifier = @"overviewCell";

    HOStoreOverviewCell *cell = (HOStorwOverviewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
     UIViewController *c = [[UIViewController alloc] initWithNibName:@"HOStoreOverviewCell" bundle:[NSBundle mainBundle]];
     cell = (HOStoreOverviewCell *)c.view;
    }

    HOStore *itemAtIndex = (HOStore *)[self.infoController storeInListAtIndex:indexPath.row];

    cell.storeName.text = itemAtIndex.name;
    cell.distance.text = [itemAtIndex niceDistance];
    cell.hours.text = [itemAtIndex.currentHour niceHours];
    NSLog(@"%@", cell);

    return cell;
}

HOStoreOverviewCell is my custom UITableViewCell in the NIB, and it contains three UILabels (storeName, distance, and hours). So this code attempts to dequeue a reusable cell, and if it can't, it creates a new one by loading it from the NIB. Then it sets the UILabels' text to be relevant bits of information from items (HOStore's) in an array. Pretty standard stuff.

My problem is this: Most of the cells display properly, but now and then (I haven't been able to reliably reproduce this) the UITableView will "miss" a cell - for example, it will display the 10th cell and the 12th cell but not the 11th cell. There is a blank spot instead where the 11th cell should be, and tapping on this spot produces no effect. Tapping anywhere below the blank spot will give me the didSelectRowAtIndexPath:indexPath delegate method with indexPath.row always set to the missing index (eg 11).

The root of the problem appears when looking at the NSLog output (excerpt):

2009-08-26 00:22:29.292 AppName[380:207] <HOStoreOverviewCell: 0x42c9880; baseClass = UITableViewCell; frame = (0 660; 320 66); autoresize = W; layer = <CALayer: 0x42c9a60>>
2009-08-26 00:22:30.331 AppName[380:207] <HOStoreOverviewCell: 0x42c9880; baseClass = UITableViewCell; frame = (0 nan; 320 66); autoresize = W; layer = <CALayer: 0x42c9a60>>
2009-08-26 00:22:32.138 AppName[380:207] <HOStoreOverviewCell: 0x42c71d0; baseClass = UITableViewCell; frame = (0 594; 320 66); autoresize = W; layer = <CALayer: 0x42c73b0>>

Note the nan in frame in the second line. This corresponds to the cellForRowAtIndexPath:indexPath callback that I get when the "blank" cell scrolls into view.

Any ideas about what might be causing this?

+1  A: 

This section of the code is curious:

if (cell == nil) {
            UIViewController *c = [[UIViewController alloc] initWithNibName:@"HOStoreOverviewCell" bundle:[NSBundle mainBundle]];
            cell = (HOStoreOverviewCell *)c.view;
    }

Why are you allocing a generic UIViewController here? That looks like a memory leak to me, as no one's going to be calling release on it.

You should be doing something more like this

if (cell == nil)
{
 cell = [[[HOStoreOverviewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier] autorelease];
}

Your performance will suffer if you load your table cells from a Nib. You're much better off from allocing them in code. I've read about this a few times on the Apple Dev Forums, and also experienced this myself (using Nibs will cause your table to be "laggy").

Shaggy Frog