smtlaissezfaire
smtlaissezfaire

Reputation: 436

dequeueReusableCellWithIdentifier returns wrong cell

I have a UITableView that uses custom cells, loaded from nibs, and hooked up to a controller (using initWithNibName:bundle:). Basically, I've noticed that dequeueReusableCellWithIdentifier returns a cell that has already been loaded, but when it shouldn't.

Here are my delegate methods:

- (UITableViewCell *) tableView: (UITableView *) tv cellForRowAtIndexPath: (NSIndexPath *) indexPath {
  return [[self controllerForTableView: tv cellForRowAtIndexPath: indexPath] cell];
}

- (TableViewCellBaseController *) controllerForTableView: (UITableView *) tv cellForRowAtIndexPath: (NSIndexPath *) indexPath {
  [self checkValidTableView: tv];

  UIViewController *controller;
  Class class;
  Event *event;
  int row = [indexPath row];

  DLOG(@"at index path row: %i", row);

  if (row == [currentEvents count]) {
    controller = [self tableCellContainerFromNibName: nibName
                                           tableView: tv
                                             atIndex: row
                                           withClass: class];
  } else {
    class = [EventFeaturedTableViewCell class]; // TODO: OR class = [EventNonFeaturedTableViewCell class];
    event = [self findEventFromIndex: row];

    lastSelectedEvent = event;
    DLOG(@"event: %@", event);

    controller = [self tableCellContainerFromNibName: NSStringFromClass(class)
                                           tableView: tv
                                             atIndex: row
                                           withClass: class
                                             perform: @selector(initTableCellWithController:)
                                                  on: self];
  }

  return controller;
}

- (TableViewCellBaseController *) tableCellContainerFromNibName: (NSString *) nibName
                                                      tableView: (UITableView *) tableView
                                                        atIndex: (int) index
                                                      withClass: (Class) class
                                                        perform: (SEL) selector
                                                             on: obj {

  CustomTableViewCell *cell = (CustomTableViewCell *) [tableView dequeueReusableCellWithIdentifier: nibName];
  TableViewCellBaseController *controller;

  DLOG(@"Cell: %@", cell);
  DLOG(@"Cell Identifier: %@", nibName);

  if (cell == nil) {
    controller = [[class alloc] initWithNibName: nibName bundle: nil];

    if (obj) {
      [obj performSelector: selector withObject: controller];
    }

    // run this after setting data as controller.view eager loads the view
    cell = controller.cell = controller.view;
    cell.controller = controller;
  } else {
    controller = cell.controller;

    if (obj) {
      [obj performSelector: selector withObject: controller];
    }
  }

  return controller;
}

- (void) initTableCellWithController: (EventsIndexTableViewCell *) controller {
  controller.event = lastSelectedEvent;
}

The Custom Cells have been hooked up in IB to the controller using the controller's view property as well as a 'cell' property. The Custom Cells have a unique identifier set directly in the nib.

I've already verified that the data in the controller is correct.

Here's the effect I'm seeing in the simulator:

http://screencast.com/t/NI2Tpc7GKEi

Notice that the event 'Atlantic Bay' shows up first in the table, then later on in the table. When scrolling back up, it no longer shows up as the first entry in the table!

Upvotes: 0

Views: 3382

Answers (1)

Rob Napier
Rob Napier

Reputation: 299275

To continue viggio24's line, I agree that I don't see a place that you're properly reconfiguring the cell. When you -dequeue... you're going to get a cell that already has "stuff" in it. It's your job to reset everything visible.

You should also read carefully Loading Custom Table-View Cells From Nib Files. Typically you use -loadNibNamed:owner:options: for this, rather than -initWithNibName:bundle:.

Upvotes: 2

Related Questions