Friday, April 15, 2011

iPhone SDK: Inserting and updating a UITableView with a new row

Hi All, I have a tableView that needs to be updated after information has been inserted from another view. If I perform a

[self.tableView reloadData];

The very next time I insert more information in another view and try to reload the table, all the currently visible rows are duplicated.

In other words, when I start up the app I have:

tableView:
    Row 1
    Row 2

Then I submit some information that will also show up in the table and suddenly I have:

tableView
    Row 1
    Row 2
    Row 3 <- info I just added
    Row 1
    Row 2

My numberOfRowsInSection implementation looks like this:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [ItemsController sharedItemsController].count;
}

My cellForRowAtIndexPath implementation looks like this:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    ItemsController* controller = [ItemsController sharedItemsController];
    NSMutableArray* recentItems = controller.listOfRecentItems;

    CustomCell *cell = nil;
    NSUInteger row = [indexPath row];

    if( row < recentItems.count )
    {
     Items*  item = [recentItems objectAtIndex:row];
     if( recentCellData == nil )
      recentCellData = [[NSMutableDictionary alloc] initWithCapacity:[indexPath length]];

     if( [recentCellData count] > 0 )
      cell = [recentCellData objectForKey:[NSString stringWithFormat:@"%d", row]];
     if (cell == nil) {
      UIViewController * view1 = [[UIViewController alloc] initWithNibName:@"CustomCell" bundle:nil];

      cell = (CustomCell*)[view1 view];

      [recentCellData setObject:cell forKey:[NSString stringWithFormat:@"%d",row]];
     }

       // do some other stuff here
    }
    // Set up the cell
    return cell;
}

What's the best way to update the table and avoid duplicating the currently visible rows. Thank in advance for all the help!

From stackoverflow
  • The error isn't in how you're reloading the table, it's in how you're providing data to it. Set a breakpoint in the data source methods and the method that adds new rows to see where you're going wrong.

  • I added a bit more info above.

  • You'll only end up with five items if tableView:numberOfRowsinSection: returns 5. Thats the simple answer to your question, but I see other problems here. I'm wondering why you have this test: row < recentItems.count. Is that array the same thing as [ItemsController sharedItemsController].count? You really need to be using the same array for both methods.

    (Also, it's not a syntax error, but you shouldn't use the property syntax for things that aren't declared as properties. You should write [recentItems count] instead.)

    I'm also confused by the code you use to set up the cell. Cells are meant to be reusable. That is, you create one cell, then reconfigure it every time in your implementation of tableView:cellForRowAtIndexPath:. Your code creates a cell for each item in your list. This is very memory-inefficient, and will likely crash your program due to insufficient memory on the iPhone if you keep lots of cells in memory like this.

    The recommended approach is to call dequeueReusableCellWithIdentifier:. If that returns nil, then you set up a cell using the initWithFrame:reuseIdentifier: initializer. The table view is very smart, and will only ask you to redraw the cell when it needs you to.

    Your recentCellData dictionary looks really shaky to me, too. What if you insert an item after the item with key @"2"? All the items with key @"3" onward will need to be shifted one element to the right to work the way you expect. That's a ton of bookkeeping that seems rather unnecessary to me. If you really needed something like this -- and to be clear, I don't think you do -- why wouldn't you use an NSMutableArray, which is much easier to use?

    Jeff : I am using a NSMutableArray. It's all about about how the view is being displayed. If I quit out of the app and restart, everything is displayed as it should be.
    Alex : I was referring to recentCellData. That's a dictionary.
    Jeff : I see what you mean. Let me see if I can tackle this ...

0 comments:

Post a Comment