UITableViewCell height resize when image is downlo

2019-01-13 21:51发布

问题:

I'm using UIImageView+AFNetworking category for async image loading. Everything works fine, but I've tried a couple of things and wasn't successful when resizing the cell's height according to the downloaded image. I want the image to fit to the width of the cell but resize in height, but I don't know how to accomplish that. I've tried reloading the row where the image was downloaded but that just causes the cellForRowAtIndexPath to fire again and set everything again, etc. Almost a recursion.

I'm calculating the new image size difference and storing that in NSMutableArray and then reloading the row in the success block in UIImageView's setImageWithURLRequest:placeholderImage:success:.

I get the correct height for a couple of rows in heightForRowAtIndexPath but then, the table starts acting weird and everything is overlaying, etc.

Any ideas?

Thanks!

EDIT

I eventually used Ezeki's answer. I also wrote a post on the topic and made a sample app that uses this technique.

Check it out on here.

回答1:

You need to store downloaded image in the memory or on the disk, so next time when you will try to get image from this URL you will received from cache.

So if you do that than you will have to do something like this:

[tableView beginUpdates];

[tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

[tableView endUpdates];

And you should return new cell's height in this method of table view data source:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

I would recomend you to use SDWebImage library instead of AFNetworking because it can cache your images to memcache and disk for you and it is very easy to use. So if you decide to use it, your code of download images will be looking like this:

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

    ...

    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"]
           placeholderImage:[UIImage imageNamed:@"placeholder.png"]
                    success:^(UIImage *image, BOOL cached) {

                        // save height of an image to some cache
                        [self.heightsCache setObject:[NSNumber numberWithFloat:imHeight] 
                                              forKey:urlKey];

                        [tableView beginUpdates];
                        [tableView reloadRowsAtIndexPaths:@[indexPath]
                                         withRowAnimation:UITableViewRowAnimationFade];
                        [tableView endUpdates];
                    }
                    failure:^(NSError *error) {... failure code here ...}];

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // try to get image height from your own heights cache
    // if its is not there return default one
    CGFloat height = [[self.heightsCache objectForKey:urlKeyFromModelsArrayForThisCell] floatValue];
    ...
    return newHeight;
}


回答2:

For me this works:

You check if the cache image is available or not if it is available it is set to the image, and if not it is downloaded and then the layout of table reset by calling reload index paths.

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

BlockbusterTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:broadcastTableCellIdentifier];

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

[self configureCell:cell atIndexPath:indexPath];
return cell;
}



-(void)configureCell:(BlockbusterTableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath{
    SportData *data = [self.webShared.arrSportsData objectAtIndex:self.selectedEvent];
    BroadcastData *broadcastData = [data.broadcastData objectAtIndex:indexPath.row];

NSURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:broadcastData.image]];

AFImageDownloader *downloader = [UIImageView sharedImageDownloader];
id <AFImageRequestCache> imageCache = downloader.imageCache;

UIImage *cacheimage = [imageCache imageforRequest:urlRequest withAdditionalIdentifier:nil];
    if (cell.imgBroadcast.image != cacheimage) {
        [cell.imgBroadcast setImageWithURLRequest:urlRequest placeholderImage:[UIImage imageNamed:@"placeholder_smaller"] success:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, UIImage * _Nonnull image) {

                cell.imgBroadcast.image = image;
                [self.tableViewBroadcast beginUpdates];

                [self.tableViewBroadcast reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

                [self.tableViewBroadcast endUpdates];

        } failure:^(NSURLRequest * _Nonnull request, NSHTTPURLResponse * _Nullable response, NSError * _Nonnull error) {

        }];

    }
    else{
        cell.imgBroadcast.image =cacheimage;
    }

    cell.lblTitle.text = broadcastData.title;
    cell.lblText.text = broadcastData.text;
    cell.lblEventDateTime.text = [self eventTime:broadcastData.eventTime];
}