开发者

Incorrect cell data display when scrolling UITableView

I am facing some weird problems. Whenever I scroll my table view, my data gets replaced with other cells. Each time, it gets replaced with different cell data. I am开发者_C百科 not seeing any particular pattern in this replacement.


cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];


Here's code for how to properly reuse a cell:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"CellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {        
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell...
    cell.textLabel.text =  [array objectAtIndex:indexPath.row];

    return cell;
}

If you provide your code we could modify that instead of giving you generic examples.


If you've created a custom cell, you may have to implement prepareForReuse on your UITableViewCell subclass to clear out cell data.


I had the same issue on iOS 7 and storyboard while I never had this problem with the same code on elder Xcode-SDK versions, and trying lots of suggestions from stackoverflow, I couldn't fix it, and guess what?! Apple's TableView Programming Guide has the well-explained guide. There's even no need to use cell==nil.

So to create a custom tableview cell using storyboard that would be reused properly, you can take two different approacesh. I personally prefer the first one which is more straightforward, but I put both solutions here.

First Approach

  1. Create a project using the Master-Detail Application template and select the Use Storyboards option.
  2. On the storyboard canvas, select the master view controller.
  3. In the Identity inspector, verify that Class is set to the custom MasterViewController class.
  4. Select the table view inside the master view controller.
  5. In the Attributes inspector, verify that the Content pop-up menu is set to Dynamic Prototypes.
  6. Select the prototype cell.
  7. In the Attributes inspector, choose Custom in the Style pop-up menu.
  8. Enter a reuse identifier in the Identifier text field. This is the same reuse identifier you send to the table view in the dequeueReusableCellWithIdentifier: message.
  9. Choose Disclosure Indicator in the Accessory pop-up menu.
  10. Drag objects from the Library onto the cell. For this example, drag two label objects and position them near the ends of the cell (leaving room for the accessory view).
  11. Select the objects and set their attributes, sizes, and autoresizing characteristics.

An important attribute to set for the programmatic portion of this procedure is each object’s tag property. Find this property in the View section of the Attributes inspector and assign each object a unique integer.

Now write the code you would normally write to obtain the table view’s data. (For this example, the only data you need is the row number of each cell.) Implement the data source method tableView:cellForRowAtIndexPath: to create a new cell from the prototype and populate it with data, in a manner similar to this code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];

    UILabel *label;

    label = (UILabel *)[cell viewWithTag:1];
    label.text = [NSString stringWithFormat:@"%d", indexPath.row];

    label = (UILabel *)[cell viewWithTag:2];
    label.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row];

    return cell;
}

There are a few aspects of this code to note:

  • The string identifier you assign to the prototype cell is the same string you pass to the table view in dequeueReusableCellWithIdentifier:.
  • Because the prototype cell is defined in a storyboard, the dequeueReusableCellWithIdentifier: method always returns a valid cell. You don’t need to check the return value against nil and create a cell manually.
  • The code gets the labels in the cell by calling viewWithTag:, passing in their tag integers. It can then set the textual content of the labels.

Second Approach

If you prefer not to use tags, you can use an alternative method for setting the content in the cell. Define a custom UITableViewCell subclass with outlet properties for the objects you want to set. In the storyboard, associate the new class with the prototype cell and connect the outlets to the corresponding objects in the cell.

To use outlets for the custom cell content

  1. Add an Objective-C class named MyTableViewCell to your project.
  2. Add the following code to the interface in MyTableViewCell.h:

    @interface MyTableViewCell : UITableViewCell

    @property (nonatomic, weak) IBOutlet UILabel *firstLabel; @property (nonatomic, weak) IBOutlet UILabel *secondLabel; @end

  3. Add the following code to the implementation in MyTableViewCell.m:

    @synthesize firstLabel, secondLabel;

  4. Add the following line of code to the source file that implements the data source:

    #import "MyTableViewCell.h"

  5. Use the Identity inspector to set the Class of the prototype cell to MyTableViewCell.

  6. Use the Connections inspector to connect the two outlets in the prototype cell to their corresponding labels.

    Incorrect cell data display when scrolling UITableView

  7. Implement the data source method tableView:cellForRowAtIndexPath:

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];
    
    cell.firstLabel.text = [NSString stringWithFormat:@"%d", indexPath.row];
    cell.secondLabel.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row];
    
    return cell;
    }
    

The code gains access to the labels in the cell using accessor methods (dot notation is used here). The code can then set the textual content of the labels.


Old, but still... I've encountered this problem. If others sees this problem one day. I didn't notice, and don't remember why I did that, but I wrote the configuration of the cell INSIDE the test if (cell == nil) instead of writing it AFTER. I must have been tired this day...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜