I have what I would imagine is a very common situation that I expected to be easy to solve - an app with a UICollectionView, with an image in each cell that is fetched from an API on a web server via http/https.
I'm attempting to implement iOS 10's prefetching in UICollectionView , so that images are that are likely to be required are requested ahead of time.
It seems to me that there are various requirements that should be met for optimal prefetching:
I've looked at various existing libraries like SDWebImage and Kingfisher , and was surprised that there doesn't appear to be any way to meet the above requirements easily with either library.
For example, SDWebImage doesn't meet the second requirement - you can only cancel all prefetching , or you must create a pre-fetcher per image (which then means various other SDWebImage features, like limiting the number of concurrent requests of pre-fetched images - ie. requirement 5 - no longer work.)
Is this really a hard problem? Did I miss some obvious solution? Am I overthinking the requirements?
It seems you'll need to implement your own priority if the latest indexpath passed from prefetchItemsAt indexPaths doesn't suffice.
Requirements 1, 2, 3 and be accomplished using a Priority Queue (Sorted Heap). Requirement 4 depends on your implementation the Priority Queue. 5 is quite broad and vague, just limit the number of calls to your method for fetching. The Priority Queue takes a generic type so you can use it with an object/class that has properties for the items you wish to fetch, below I just use IndexPath.row for simplicity.
Create a priority queue that will serve as a mediator between your datasource and the cache.
then set the data to fetch from your DataSource by peeking/dequeuing the priority queue and storing in Kingfisher. Your DataSource -> 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 a sort function.
you can get a prebuilt priority queue from here you will also need a heap to create the priority queue.
more on priority Queues and heap sorting
Without the code in question it is difficult to offer an effective solution. I hope this helps, cheers and good luck!
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.