简体   繁体   中英

UITableView data displays multiple times when scrolling

I have a UITableView where the data displays but when it scrolls the data ( UILabel ) either disappear or they are added over and over again on top of each other.and every time if i scroll every cell exchange data.

here's my cellForRowAtIndexPath: code

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

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

        if(cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

        }

        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        // configure the cell's background
        UIImageView *gradient = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"gradient"]];
        [cell.contentView addSubview:gradient];

        // configure the cell's label
        UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 130, 300, 44)];

        // grab a reference to the label's text from the tableData
        nameLabel.text = [name objectAtIndex:indexPath.row];
        nameLabel.textColor = [UIColor blackColor];
        nameLabel.font = [UIFont fontWithName:@"DIN-Bold" size:12];
        nameLabel.backgroundColor = [UIColor clearColor];

        // set the autoReiszing mask -- this way if the label spills over the editing
        // [icon?] then the text will trail off in ...
        nameLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;

        [cell.contentView addSubview:nameLabel];

        // configure the cell's label
        UILabel *tableTextViewLbl = [[UILabel alloc] initWithFrame:CGRectMake(50, 80, 220, 50)];

        // grab a reference to the label's text from the tableData
        tableTextViewLbl.text = [message objectAtIndex:indexPath.row];
        tableTextViewLbl.textColor = [UIColor blackColor];
        tableTextViewLbl.font = [UIFont fontWithName:@"DIN" size:10];
        tableTextViewLbl.backgroundColor = [UIColor clearColor];
        tableTextViewLbl.autoresizingMask = UIViewAutoresizingFlexibleWidth;

        [cell.contentView addSubview:tableTextViewLbl];

        // configure the cell's label
        UILabel *tableTimeStampViewLbl = [[UILabel alloc] initWithFrame:CGRectMake(50, 30, 200, 50)];

        // grab a reference to the label's text from the tableData
        tableTimeStampViewLbl.text = [timeStamp objectAtIndex:indexPath.row];
        tableTimeStampViewLbl.textColor = [UIColor lightGrayColor];
        tableTimeStampViewLbl.font = [UIFont fontWithName:@"DIN" size:7];
        tableTimeStampViewLbl.backgroundColor = [UIColor clearColor];
        tableTimeStampViewLbl.autoresizingMask = UIViewAutoresizingFlexibleWidth;

        [cell.contentView addSubview:tableTimeStampViewLbl];

    //   UIImageView *image;
    //   UIImage *image1=[UIImage imageNamed:@"rest.png"];
    //   image=[[UIImageView alloc]initWithImage:image1];
    //   image.frame=CGRectMake(10,30,40,30);
    //   
    //   [cell.contentView addSubview:image];
    //


        return cell;

    }

You are creating a UILabel instance for every time a cell gets loaded/reloaded into view. This is not how it's done. Instead - add the UILabel as a property (probably an IBOutlet) in a UITableView subclass and alter it in cellForRowAtIndexPath: .

So you would have a new class, inheriting from UITableViewCell - let's call it MyCustomCell.

In MyCustomCell.h:

@interface MyCustomCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UILabel *nameLabel;

@end

MyCustomCell.xib will define the UILabel position and configuration and of course needs to be associated with the nameLabel property.

In cellForRowAtIndexPath, rather than instantiating a new UILabel, you would just refer to cell.nameLabel and change the text. Be sure to define a resuseIdentifier for the cell class in interface builder and instantiate it using:

MyCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"];

if (!cell) {
    cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyIdentifier"];

}

Just add following code

NSArray *subviews = [[NSArray alloc] initWithArray:cell.contentView.subviews];
for (UILabel *subview in subviews)
{
     [subview removeFromSuperview];
}
[subviews release];
subviews = nil; 

After -

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

And then add your code.

Before You follow my Answer i want to tell you that following code is bad for memory management because it will create new cell for each rows of UITableView , so be careful for it.

But it is better to use, When UITableView Have Limited rows (about 50-100 may be ) then following code is helpful in your case, use it if is it suitable for you.

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

    NSString *CellIdentifier = [NSString stringWithFormat:@"S%1dR%1d",indexPath.section,indexPath.row];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil)
    {
        cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

         /// Put your code here
     }

    return cell;
}

If you have limited rows then this is best code for you.

First of all you need to understand how UITableView works. Actually UItableView Cell concept is that every time you scroll the table view, it's not creating new cell for you, it's just reusing the cell , with help of cellIdentifier.

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; And that time we need to just update the data for cell. That's it, simply better. You can see that below:

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

    UILabel *nameLabel = nil;

    UILabel *tableTextViewLbl= nil;

    UILabel *tableTimeStampViewLbl= nil;
    //Here we are , reuse the cells...
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];



    if(cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        // configure the cell's background
        UIImageView *gradient = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"gradient"]];
        [cell.contentView addSubview:gradient];

        // configure the cell's label
        nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 130, 300, 44)];

        // grab a reference to the label's text from the tableData
        nameLabel.textColor = [UIColor blackColor];
        nameLabel.font = [UIFont fontWithName:@"DIN-Bold" size:12];
        nameLabel.backgroundColor = [UIColor clearColor];
        nameLabel.tag = 111;//Giving this component to tag so we can access it

        // set the autoReiszing mask -- this way if the label spills over the editing
        // [icon?] then the text will trail off in ...
        nameLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;

        [cell.contentView addSubview:nameLabel];

        // configure the cell's label
        tableTextViewLbl = [[UILabel alloc] initWithFrame:CGRectMake(50, 80, 220, 50)];
        tableTextViewLbl.textColor = [UIColor blackColor];
        tableTextViewLbl.font = [UIFont fontWithName:@"DIN" size:10];
        tableTextViewLbl.backgroundColor = [UIColor clearColor];
        tableTextViewLbl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        tableTextViewLbl.tag = 222;//Giving this component to tag so we can access it
        [cell.contentView addSubview:tableTextViewLbl];

        // configure the cell's label
        tableTimeStampViewLbl = [[UILabel alloc] initWithFrame:CGRectMake(50, 30, 200, 50)];
        tableTimeStampViewLbl.textColor = [UIColor lightGrayColor];
        tableTimeStampViewLbl.font = [UIFont fontWithName:@"DIN" size:7];
        tableTimeStampViewLbl.backgroundColor = [UIColor clearColor];
        tableTimeStampViewLbl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
        tableTimeStampViewLbl.tag = 333;//Giving this component to tag so we can access it
        [cell.contentView addSubview:tableTimeStampViewLbl];
    }



    nameLabel = (UILabel*)[cell.contentView viewWithTag:111];//Here we access the name label with the help of tag, is that we have assigned tag while making the componant.
    nameLabel.text = [name objectAtIndex:indexPath.row];


    tableTextViewLbl = (UILabel*)[cell.contentView viewWithTag:222];//Here we access the name label with the help of tag, is that we have assigned tag while making the componant.
    // grab a reference to the label's text from the tableData
    tableTextViewLbl.text = [message objectAtIndex:indexPath.row];


    tableTimeStampViewLbl = (UILabel*)[cell.contentView viewWithTag:333];//Here we access the name label with the help of tag, is that we have assigned tag while making the componant.
    // grab a reference to the label's text from the tableData
    tableTimeStampViewLbl.text = [timeStamp objectAtIndex:indexPath.row];


    return cell;

}

Use this way

if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
else{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}

But taking custom cell is the best answer. check this link gives best solution to custom cell

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM