Optimal image preload / prefetch in UICollectionView and UITableView

I have what I present, this is a very common situation that I expected to easily solve - an application with a UICollectionView with an image in each cell, which is extracted from the API on the web server via http / https.

I am trying to implement iOS 10 prefetching in a UICollectionView , so that images that are likely to be required are requested in advance.

It seems to me that for optimal prefetching, it is necessary to fulfill various requirements:

  • The acquisition of images that are actually needed immediately should always be prioritized above speculative prefetching, even if the image is already in the queue to be retrieved.
  • When iOS tells us that a particular image is no longer required to be pre-programmed, it (and only it) should be removed from the prefetch queue.
  • If an image is requested, it should always be delivered if / all / requests for it are canceled (it is easy to make a mistake if one image is used in several cells or in several viewing dispatchers).
  • Priority sampling should be aborted if didEndDisplaying is called (but if the requested prefetch has not been canceled, the image must be left in the lower priority queue).
  • Various general requirements that are simply related to uploading images - for example. Do not flood the base system with prefetch requests, which ultimately reduce the throughput and server slots from the required immediate images.

I looked through various existing libraries, such as SDWebImage and Kingfisher , and was surprised that there seems to be no way to easily satisfy the above requirements with any library.

For example, SDWebImage does not meet the second requirement - you can cancel all prefetching , or you must create a pre-fetcher per image (which then means various other SDWebImage functions, such as limiting the number of simultaneous requests for pre-drawn images - i.e. requirement 5 - does not work any more.)

Is this a really serious problem? Am I missing some obvious solution? Am I exceeding the requirements?

+5
source share
1 answer

It seems you need to implement your own priority if the last index path passed from prefetchItemsAt indexPaths is not enough.

Requirements 1, 2, 3 and are performed using the priority queue (sorted heap). Requirement 4 depends on your implementation in the priority queue. 5 is pretty wide and vague, just limit the number of calls to your method to retrieve. The priority queue takes on a generic type, so you can use it with an object / class that has properties for the elements you want to extract, below I just use IndexPath.row for simplicity.

Create a priority queue that mediates between your data source and the cache.

then set the data to retrieve from your data source by searching / deleting the priority queue and saving to Kingfisher. Your data source -> PriorityQueue -> Kingfisher -> Cell

func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) { ... for indexPath in IndexPaths { //Add the indexPath to the top of the priority queue //highest priority is determined by the sort function you used when initializing the priority queue. priorityQueue?.enqueue(indexpath.row) } //Call your method for getting the properties self.fetchObjectsByPriority() } func fetchObjectsByPriority() { if let count = priorityQueue?.count { for _ in 0...count { //get the index var index = self.priorityQueue?.dequeue() //Alternatively .peek() with out dequeuing item //get image data and store dataSource[index].image = ... } } } 

make sure you initialize the priority queue with the sort function.

you can get a pre-created priority queue from here you will also need a heap to create a priority queue.

more priority queues and heap sorting

Without the appropriate code, it is difficult to offer an effective solution. Hope this helps, cheers and good luck!

0
source

Source: https://habr.com/ru/post/1270217/


All Articles