简体   繁体   中英

Have to scroll UITableView to update cell height

Currently I am using an outlet of the imageView height constraint in order to adjust the height of the imageView like so:

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


 cell.productImageView.file = (PFFile *)object[@"image"];
        [cell.productImageView loadInBackground:^(UIImage * _Nullable image, NSError * _Nullable error) {

            cell.imageHeightConstraint.constant = image.size.height / image.size.width * cell.cardView.frame.size.width;
            [cell.productImageView setNeedsUpdateConstraints];


            [UIView animateWithDuration:0.50f animations:^{
                [cell.cardView layoutIfNeeded];
            }];


        }];

In viewDidLoad

self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 350;

Is there a better way to change the height of the ImageView than to use a outlet to the height constraint?

I have to end up scrolling to have it update to the updated height constraint.

reload your tableView in viewWillAppear or viewDidAppear something like this,

 -(void)viewDidAppear:(BOOL)animated{

    [self.tableView reloadData];

  }

I doubt if your code is also resizing the cell based on image height. Inside the block where you update the imageView height constraint also put this code:

let indexPath = self.tableView.indexPathForCell(cell)
                if indexPath != nil {
                    self.tableView.beginUpdates()
                    self.tableView.endUpdates()
                }

Objective C :

NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
if (indexPath != nil) {
    [self.tableView beginUpdates];
     [self.tableView endUpdates];
}

You should only modify the UI on the main thread. This means that you should change your callback from this:

[cell.productImageView loadInBackground:^(UIImage * _Nullable image, NSError * _Nullable error) {
    // code here
}];

to this, which uses Grand Central Dispatch to run on the main thread.

[cell.productImageView loadInBackground:^(UIImage * _Nullable image, NSError * _Nullable error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        // code here. Will be run after dispatch_async returns. 
    });
}];

Edit :
This will be slow because -tableView:cellForRowAtIndexPath: , and therefore -tableView:cellForRowAtIndexPath:object: are called whenever a cell scrolls into view. It is better to cache your images (both for performance and for your users' mobile data). A built-in way to do this is NSCache . To do this, add a property to your class:

@property (strong, nonatomic) NSCache *cache;

Then, in your viewDidLoad , create your cache:

self.cache = [[NSCache alloc] init];

When you load an image in -tableView:cellForRowAtIndexPath:object: , do something like this:

void (^updateView)(UIImage *) = ^(UIImage * _Nullable image) {
    cell.imageHeightConstraint.constant = image.size.height / image.size.width * cell.cardView.frame.size.width;
    [cell.productImageView setNeedsUpdateConstraints];


    [UIView animateWithDuration:0.50f animations:^{
        [cell.cardView layoutIfNeeded];
    }];

}];
UIImage *cached = [self.cache objectForKey:cell.productImageView.file];
if (cached) {
  cell.productImageView.image = cached;
  updateView(cached);
} else {
    [cell.productImageView loadInBackground:^(UIImage * _Nullable image, NSError * _Nullable error) {
        if (!error) {
            [self.cache setObject:image forKey:cell.productImageView.file];
        }
        updateView(image);
    }];
}

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