简体   繁体   中英

UITableView image changing while scrolling

I have a UITableView with custom cell . Custom cell contains a UIView . The image loaded here asynchronously. But when scrolls my table view, the images in the cell changes. Here is my code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"MyCell";
    MSAppointmentsModel *data = [self.appointments objectAtIndex:indexPath.row];

    MSAppointmentsCell *cell = (MSAppointmentsCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        NSArray *ar = [[NSBundle mainBundle] loadNibNamed:[Common checkDeviceforController:@"MSAppointmentsCell"] owner:nil options:nil];
        for (id eachObject in ar) {
            if ([eachObject isKindOfClass:[UITableViewCell class]]) {
                cell = eachObject;
            }
        }
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            NSURL *imgUrl = [NSURL URLWithString:[data.cusDetails objectForKey:@"customer_image"]];
            NSData *imgData = [NSData dataWithContentsOfURL:imgUrl];
            UIImage *image = [UIImage imageWithData:imgData];
            dispatch_sync(dispatch_get_main_queue(), ^{
                [cell.medallionView setImage:image];
            });
        });

        if (data.comp_status == YES) {
            cell.status.image = [Common imageResize:[UIImage imageNamed:@"CheckMark_green.png"] andResizeTo:cell.status.frame.size];
        }

    }

    cell.custName.text = [data.cusDetails objectForKey:@"customer_name"];
    cell.service.text = [data service];
    cell.empName.text = [NSString stringWithFormat:@"by %@",[data.empDetails objectForKey:@"employee_name"]];


    return cell;
}

Please help me.

Try this,

1: Take Array for caching image NSMutablearray * imageicons;

2: after downloading data add NULL values into array;

 imageicons=[[NSMutableArray alloc] init];

 for (int i=0; i<[self.appointments count]; i++) 
{
 [imageicons insertObject:[NSNull null] atIndex:i];
}

3:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
  if(indexPath.row < [imageicons count] && [imageicons objectAtIndex:indexPath.row] != [NSNull null] )
        {
            [cell.bookimage setImage:[imageicons objectAtIndex:indexPath.row]];
            NSLog(@"Array Hit");

        }
        else{
        NSLog(@"Count of %i Size of %li Array and row number %i",[imageicons count],sizeof(imageicons),indexPath.row);
      [NSThread detachNewThreadSelector:@selector(DownloadImageInBackground:) toTarget:self withObject:indexPath];
        }
 }

-(void)DownloadImageInBackground:(NSIndexPath *)path
{
MSAppointmentsModel *data = [self.appointments objectAtIndex:indexPath.row];
NSString *str=[data.cusDetails objectForKey:@"customer_image"];

  imagetodisplay  = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:str]]];

if (imagetodisplay==Nil)
{

  // set deault image
     [imageicons replaceObjectAtIndex:path.row withObject:[UIImage imageNamed:@"defaultimg.png"]];
}
else
{

    MSAppointmentsCell *cell=(MSAppointmentsCell *)[self.booktableview cellForRowAtIndexPath:path];
    [cell.bookimage setImage:imagetodisplay];
    //NSLog(@"Count of %i Size of %li Array and row number %i",[imageicons count],sizeof(imageicons),path.row);

    [imageicons replaceObjectAtIndex:path.row withObject:imagetodisplay];


}

}

Try adding a setNeedsDisplay call on your imageView after cell.empName.text = ...

Sorry I overlooked something. updated.

I would assume medallionView holds the image, so there are a few problems.

You experience the error because you dequeue a Cell, but don't only set the custName, service and empName label's text, not the image view (medallionView). So basically, it draws (screensize / cellheight) number of rows (example 9), populates those cells, then keeps reusing them, with what image it finds there.

Also, when I did async requests, I was told never to draw inside the async request, instead just get all the images from the URL and store them in an Array, then when everything loaded, 1) notify the tableView delegate class to reload the data OR 2) have a delegate method, which gets performed AFTER data is loaded OR 3) Have a completion block, which gets performed after every image is loaded.

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