0

I'm using UITableView with various kinds of cells defined in the storyboard. The styles are all "Subtitle." For one cell type, the Identifier is "label," it's used in my table in two locations, and is fetched thusly:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"label" forIndexPath:indexPath];

The code to populate the text labels is:

// cell {0,0} {section,row}
cell.textLabel.text = @"";
cell.detailTextLabel.text = @"Subtitle 1";
NSLog(@"%@",cell); // <UITableViewCell: 0x13ee183c0; frame = (0 26; 320 52); text = ''; ...

And

// cell {6,0}
cell.textLabel.text = @"Version";
cell.detailTextLabel.text = @""; // using @" " instead cures the problem
NSLog(@"%@",cell); // <UITableViewCell: 0x13ee183c0; frame = (0 1022; 320 52); text = 'Version'; ...

At launch, cell {0,0} shows the proper text. When I scroll down, cell {6,0} shows the proper text. But, when I scroll back to the top, cell {0,0} is blank (the reused cell.text = 'Version'). If I scroll cell {0,0} out of view, then scroll back to the top, cell {0,0} is okay (the reused cell.text = '').

In cell {6,0}, if I use @" " instead of @"" for detailTextLabel, then the problem goes away, but the spacing in the cell is incorrect ("Version" is no longer vertically centered).

It's curious that cell.text (a deprecated property) is not empty in the second case, but explicitly setting cell.text back to nil or @"" in {0.0} makes no difference.

Why is the first cell blank when reused in section 6?

EDITED TO ADD:

Here is a simplified version of my code that still demonstrates the problem.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 10;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *resueIdentifier;
    if ( indexPath.section == 0  &&  indexPath.row == 0 ) {
        resueIdentifier = @"label"; // in the nib, this is a cell with no other controls
    } else if ( indexPath.section == 6  &&  indexPath.row == 0 ) {
        resueIdentifier = @"label";
    } else { // all other rows for demo contain a UISwitch
        resueIdentifier = @"switch"; // in the nib, this is a cell with a UISwitch (e.g., Settings)
    }
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:resueIdentifier forIndexPath:indexPath];
    // never nil -- that always returns a cell from the storyboard/nib

    if ( indexPath.section == 0  &&  indexPath.row == 0 ) {
        cell.textLabel.text = @""; // no title
        cell.detailTextLabel.text = @"This is detail text";
    } else if ( indexPath.section == 6  &&  indexPath.row == 0 ) {
        cell.textLabel.text = @"Version X";
        cell.detailTextLabel.text = @""; // no detail text (this causes the problem)
    } else {
        cell.textLabel.text = @"X";
        cell.detailTextLabel.text = @"Y";
    }
    return cell;
}

To see the issue, scroll down to section 6 (see "Version X" in the cell), then scroll back to the top. The top row will be empty (should display "This is detail text"). Next scroll down so row 0 is out of view, then scroll back to the top (row 0 will show the detail text).

Here's a sample of my storyboard (the "label" row is selected): Storyboard

Jeff
  • 2,659
  • 1
  • 22
  • 41
  • Paste in the whole code of cellForRowAtIndexPath – Shai Jul 06 '15 at 08:41
  • Without seeing the entire method it's hard to say where things are going wrong - but from what you've put here it makes me want to ask if it's necessary to use dynamic cells if you're expecting static content in a specific location? You may want to consider static cells if you have explicit content. – Derek Lee Jul 06 '15 at 09:00
  • @Shai: I've added more code. – Jeff Jul 07 '15 at 08:38
  • @Derek: My UITableView is a settings page. Each cell can have a switch, a slider, a stepper, etc., and there's one (dynamic) prototype for each of those types. One type is "label" (the Identifier) and has no added controls. The particular type for each section and row is specified in a lookup table, along with the text and other specifics about the row. If I want to change the UITableView rows, I just change the lookup table. – Jeff Jul 07 '15 at 08:38

2 Answers2

0

Please use this:

 static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        NSLog(@"new one");
    }

Hope this could help/

Nghia Luong
  • 790
  • 1
  • 6
  • 11
  • When using a storyboard with prototype cells, dequeueReusableCellWithIdentifier:forIndexPath: never returns nil. – Jeff Jul 07 '15 at 08:36
0

Solution: add [cell layoutIfNeeded] at the end of tableView:cellForRowAtIndexPath: (Might this be an Apple bug when using a storyboard with various types of prototype cells?)

Suggested by https://stackoverflow.com/a/27699358/236415

Community
  • 1
  • 1
Jeff
  • 2,659
  • 1
  • 22
  • 41
  • Yes, this is an iOS8 bug fixed in iOS9. See http://stackoverflow.com/questions/25793074/subtitles-of-uitableviewcell-wont-update . – Carl Lindberg Nov 05 '15 at 15:25