There is a requirement to show a list of images that fetched from the internet, such as the scene of product’s detail in Taobao app. Have a glance of the effect first.
(The gif is a little large.)
Each cell contains simply an image view that covers the whole cell. The difficulty is that before we have got the image, we do not know the proportion of its width and height, making it hard to define the height of cells. However, the table view should be loaded at once in order to put some place holders on it.
Thus, we should divide the whole process into two parts:
- Show the place holder and to download the image.
- Reload to show the image when appropriate.
I would like to choose YYWebImage as a web image loading framework. Of course, there are other choices and I just take an example.
The Core
The downloaded images will be stored in a NSMutableDictionary or NSCache and the keys are the index of the cell so we can ignore the order of downloading. If the wanted data is ready, return the data. Or, just return the place holder.
1 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { |
When to reload
We now know how to determine whether to return the place holder and download the image or return the downloaded image directly. But when is the appropriate timeing to reload the table view in order to replace the place holder to the wanted image?
The easiest way is to reload the corresponding index path as soon as the image is downloaded.
1 | self.cellImages[@(indexPath.row)] = image; |
But in this way, the content offset jumps randomly even when I am dragging the table view. Thus I add a property to mark whether the table view should be reloaded. (If the table view is not being draging, just reload it at once)
1 | self.cellImages[@(indexPath.row)] = image; |
Then reload it when it stop moving.
1 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { |
That’s for today.