Search code examples
iosswiftuicollectionviewalamofirealamofireimage

Swift - AlamofireImage download multiple URLs and display in CollectionView


I would like to download multiple URLs from string in array, and display images in collectionView. I succeed to display four images (4 visible cells on my screen) and when I scroll, that begins the download of the 2 other images.

I want that these 6 images are downloaded in the same time (and I don't have to scroll for beginning the other download). After this, I want to display the total time spent to download and display images in my collectionView.

What I am doing wrong ?

Here is my code :

import UIKit
import AlamofireImage
import Alamofire

class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource {

    var players = [
        ["image_Name":"https://images.unsplash.com/photo-1420768255295-e871cbf6eb81?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&s=4b94ef340bd7f6cac580fbc76af326af"],
        ["image_Name":"https://images.unsplash.com/photo-1465411801898-f1a78de00afc?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&s=149d27223217c0fa63c7dd8f1e8d23f6"],
        ["image_Name":"https://images.unsplash.com/photo-1466853817435-05b43fe45b39?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&s=a3b629b7e0c4f710ce119f219ae5b874"],
        ["image_Name":"https://images.unsplash.com/photo-1467404899198-ccadbcd96b91?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&s=66eef8db7a0aa4119c6c8d7ba211f79f"],
        ["image_Name":"https://images.unsplash.com/photo-1470322346096-ecab3914cab7?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&s=83863ba23662871baf6434c6000e00bd"],
        ["image_Name":"https://images.unsplash.com/photo-1473624566182-509e437512f4?ixlib=rb-0.3.5&q=80&fm=jpg&crop=entropy&cs=tinysrgb&s=54c3ec6d1fee824d62e6fa76676ddf17"]
    ]
    var methodStart = Date()

    @IBOutlet weak var mycall: UICollectionView!
    var selectedIndex=[Int]()

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.players.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell:playerCell = collectionView.dequeueReusableCell(withReuseIdentifier: "playerCell", for: indexPath) as! playerCell

        let url = URL(string:self.players[indexPath.row]["image_Name"]!)
        if indexPath.row == 0 {
           methodStart = Date()
        }
        Alamofire.request(url!).responseImage { response in
            //            debugPrint(response)
            //            print(response.request)
            //            print(response.response)
            //            debugPrint(response.result)

            if let image = response.result.value {
                cell.playerImage.image = image
            }
        }

        if indexPath.row == self.players.count - 1 {
            let methodFinish = NSDate()
            let executionTime = methodFinish.timeIntervalSince(methodStart as Date)
            print("Execution time: \(executionTime)")
        }

        return cell
    }
}

Solution

  • Problem in your code -

    you said you want those 6 images to be downloaded at the same time and when user scrolls the 5th and 6th image should display immediately. but this is not happening because the cellForItemAtIndexPath function for the 5th and 6th cell called when you scroll. this is the default behavior and you cannot invoke this before user scrolled.

    Quick fix solution -

    Download all the images outside cellForItemAtIndexPath function, like in either viewDidLoad or viewDidAppear by looping the array of players and then reload the collection view after completion of download of the last one.

    Permanent and best solution -

    Implement lazy loading and caching of images using either Heneke or SDWebImage to display image in cells. And use prefetch option in those libraries to fetch images before they were shown in cells. To use prefetch option you need to loop through the array and pass the urls to the fetching and storing functions of the library and just load image in cell according to the syntax of that library and it will manage the displaying of image when it downloaded and you don't have to worried about that.