0
votes

My UITableView needs to display some images from server. UITableViewCell is consisted of single UIImageView and NSLayoutConstraint for the height of UIImageView.

In cellForRowAtIndexPath in the view controller, it fetches image from server and resizes image to the fit width of screen. One important thing is that image needs to keep aspect so I made a code to get a height of image keeping the aspect. The height is applied to the layout constraint which is for the height of image view.

Unless I call [tableView beginUpdates] and [tableView endUpdates] method, the cell does not resizes so I call those methods after every image for cell is loaded. The problem is when user is scrolling the table view while fetching image and beginUpdates and endUpdates method are being called, the scroll jumps to some point. (I'm not sure where the table view is jumping to)

This is what I tried to prevent jumping:

- (void)resizeCellHeight {
    [UIView performWithoutAnimation:^{
        self->currentScrollY = self.tableView.contentOffset.y;

        [self.tableView beginUpdates];
        [self.tableView endUpdates];

        self->currentScrollY = -1;
    }];
}


- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if(currentScrollY != -1) {
        [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, currentScrollY) animated:NO];
    }
}

Sometimes it worked, but not 100%. This code sometimes even prevented decelerating and kept jumping.

Is there anyway to prevent scroll view from jumping? or a better way to figuring the cell?

1

1 Answers

0
votes

Fetching data in cellForRow is not ok. It's time consuming and you are blocking the main thread.

All server related items must be done on another thread, and when it finishes you reload the tableView (or a specific item from it).

If you know the image size you can create the cell using the size of the image in your imageView and then just refresh the cell using [tableView reloadAtIndexPaths:] after you have the data from the server for that row.

To keep the aspect ratio just set the contentMode of the imageView to .aspectFit.

To fully answer your question you need the rethink the process. Move everything related to server on another thread. When items available, reload the cell. Try to create the cells with a fixed size, and just refresh it when you have the data. Set the imageView contentMode to aspectFit.