Preloading Images in iOS

I developed an application that shows "full-screen maps" in a UICollectionView as a Tinder. The map contains image and text. I uploaded the image using the SDWebImage sd_setImageWithURL method in a UICollectionView cell.

However, this did not give me good performance, since the images were loaded mainly when the user was on the map. Therefore, I used the SDWebImagePrefetcher prefetch queue to do this as follows: -

 func startImagePreloadingOperationForIndex(index:Int) { let numberOfImagesToBePreloadedOnEachSide = 20 var previousIndex = index - numberOfImagesToBePreloadedOnEachSide var nextIndex = index + numberOfImagesToBePreloadedOnEachSide if previousIndex < 0 { previousIndex = 0 } if nextIndex >= currentNewsCollection.count { nextIndex = currentNewsCollection.count - 1 } if previousIndex >= nextIndex || currentNewsCollection.isEmpty { return } let arrayOfNewsStories = currentNewsCollection[previousIndex...nextIndex] let arrayOfImageURLs = arrayOfNewsStories.map( { ImageUtility.getImageStringForNewsStory($0) } ) SDWebImagePrefetcher.sharedImagePrefetcher().prefetchURLs(arrayOfImageURLs, progress: { (x, y) -> Void in }) { (x, y) -> Void in } } 

This function is called when the user lands on a specific map. The prefetch queue automatically controls the loading of images into the cache, so I donโ€™t have to worry about that. Along with this, I also use sd_setImageWithURL in cellForItemAtIndexPath to load the loaded image from the cache.

This is the best solution, since now I preload the images when the user is on the map. However, this is a parallel queue. This means that the image is not. index + 20 may be loaded before the current image, and the user may need to wait for the image. Also, the application becomes a little backward if the user scrolls over 50 cards, and memory usage also continues to grow.

Can anyone suggest improvements to this or a better algorithm?

thanks

+7
ios image swift uicollectionview sdwebimage
source share
3 answers

Load the image on the current map using sd_setImageWithURL, and in the completion handler, start loading the prefetch queue. Thus, the current image always has the highest priority and does not lag behind.

 currentCardImageView.sd_setImageWithURL(url) { (image, error, imageCacheType, url) in // start prefetching here } 

If the current image is already loaded, SDWebImage recognizes this and extracts it from the cache.

Another problem with latency and high memory consumption can be solved by reducing the amount of pre-loaded image. 20 is high enough, 5 should be enough, but it depends on image size, network speed, etc.

Another thing: SDWebImage has the property maxConcurrentOperationCount. Start with 1, check, increase to 2, check, increase ... and so on. Until you find that he is behind.

+5
source share

I would suggest processing your own queue, saving the images to disk, and then downloading them from disk.

Instead of a parallel queue, use a serial queue, or at least reduce the number of parallel connections

+1
source share

I solved a similar problem in the application that I am developing. There are thousands of users in my application, and everyone can have an avatar.

To improve performance, I developed a level 3 controller to manage avatar request.

First I check for NSCache (all the most recent avatars I use are stored in NSCache, which is handled by iOS, so I donโ€™t have to worry about releasing cache if necessary). You just need to define a few parameters to configure NSCache.

If an avatar is not found in NSCache, I check my local Db (Sqlite), where the most recently used avatars are saved as Blob fields. Just remember that sometimes you need to perform a cleanup on a local Db, letting go of the old data to save the deviceโ€™s memory.

If still not found, I save the request in the queue using the LIFO method (the latter in the first case). This means that whenever a local user scrolls the list of users, the current user avatars on the screen should be received before those that were already outside the table view screen.

Once again, in order to increase productivity again (decide it of your choice), while the user scrolls the screen quickly, I do not request any download. I just start asking for downloads when the user slows down the table scrolling. In addition, I limit the number of concurrent downloads. A new download starts only when the download slot is opened (upon successful completion or failure).

These optimizations work very well for me, my application works light.

I hope this can help you.

+1
source share

All Articles