简体   繁体   中英

iOS: UITableView cells gets mixed up while scrolling

I am facing one issue regarding UITableView cells get mixed up while scrolling, specially for images.

I am not sure why this is going one.
I have change the patter for displaying then also its get mixed up.
Below is my code.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"FriendsCell";
    FriendsTableCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"FriendsTableCell" owner:self options:nil];
        cell = [nib objectAtIndex:0];
    }

    return cell;
}

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    FriendsTableCell *simpleTableCell = (FriendsTableCell *)cell;

    _model = [_contentArray objectAtIndex:indexPath.row];

    simpleTableCell.nameLabel.text = _model.fullname;

    if(_friendsSegmentControl.selectedSegmentIndex == 0) {

        simpleTableCell.followButton.hidden = NO;
        simpleTableCell.removeButton.hidden = NO;
        simpleTableCell.unBlockButton.hidden = YES;
        simpleTableCell.ignoreRequest_btn.hidden = YES;
        simpleTableCell.rejectRequest_btn.hidden = YES;
        simpleTableCell.acceptRequest_btn.hidden = YES;

        simpleTableCell.removeButton.tag = indexPath.row;
        [simpleTableCell.removeButton addTarget:self action:@selector(deleteFriend_btn:) forControlEvents:UIControlEventTouchUpInside];

        simpleTableCell.followButton.tag = indexPath.row;

        if([_model.isfollowed isEqualToString:@"YES"]) {
            [simpleTableCell.followButton setImage:[UIImage imageNamed:@"follow_yellow.png"] forState:UIControlStateNormal];
            [simpleTableCell.followButton addTarget:self action:@selector(unfollowFriend_btn:) forControlEvents:UIControlEventTouchUpInside];
        }
        else {
            [simpleTableCell.followButton setImage:[UIImage imageNamed:@"follow_white.png"] forState:UIControlStateNormal];
            [simpleTableCell.followButton addTarget:self action:@selector(followFriend_btn:) forControlEvents:UIControlEventTouchUpInside];
        }
    }

    NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL,(__bridge CFStringRef) _model.prof_pic,NULL,(CFStringRef)@"!*'();:@&=+$,/?%#[]",kCFStringEncodingUTF8));

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
    dispatch_async(queue, ^(void) {

        NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.touristtube.com/%@",escapedString]]];
        UIImage *image = [UIImage imageWithData:imageData];
        dispatch_async(dispatch_get_main_queue(), ^{
            simpleTableCell.profileImageView.image = image;
        });
    });

}

Two things you need to ensure while creating cells for table view-

1) Regarding reusable cells - As you are using reusable cells, so in case if it's dequeued it will show the data for the index path for which it was originally created.

It's right that you are updating each cell(whether newly created/ dequeued) with the data for the corresponding index path just before displaying it in

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

Also you can update the data for each cell' container for corresponding index path in

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

as well.

So, please ensure if the cell is reused you should update the data of each container(cell's subviews) with the data for the current index path. Doing so will resolve your issue of cell's content getting overlapped.

2) Regarding asynchronously downloading the images for cells - Also as you are downloading the images asynchronously, so it will not block the main thread and as soon as the image is downloaded you need to switch to main thread to set the image to the cell.

Now the thing to remember in case of asynchronous image downloading is that you should always access the cell for the correct index path on main thread and set the downloaded image to the cell's image view for the index path for which it was scheduled to be downloaded.

So for the images you should update your image downloading method as

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
    dispatch_async(queue, ^(void) {

        NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://www.touristtube.com/%@",escapedString]]];
        UIImage *image = [UIImage imageWithData:imageData];
        dispatch_async(dispatch_get_main_queue(), ^{
           FriendsTableCell *cell = [tableView cellForRowAtIndexPath:indexPath];
            cell.profileImageView.image = image;
            [cell setNeedsLayout];
        });
    });

this will resolve your issue of cell's image intended to be displayed for a index path but actually showing on a cell at some other index path.

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