how to implement lazy loading of images in table view using swift how to implement lazy loading of images in table view using swift ios ios

how to implement lazy loading of images in table view using swift


Old Solution:

Since you doesn't show any code.

Here is the example for you.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {    // try to reuse cell    let cell:CustomCell = tableView.dequeueReusableCellWithIdentifier("DealCell") as CustomCell    // get the deal image    let currentImage = deals[indexPath.row].imageID    let unwrappedImage = currentImage    var image = self.imageCache[unwrappedImage]    let imageUrl = NSURL(string: "http://staging.api.cheapeat.com.au/deals/\(unwrappedImage)/photo")    // reset reused cell image to placeholder    cell.dealImage.image = UIImage(named: "placeholder")    // async image    if image == nil {    let request: NSURLRequest = NSURLRequest(URL: imageUrl!)    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in        if error == nil {            image = UIImage(data: data)            self.imageCache[unwrappedImage] = image            dispatch_async(dispatch_get_main_queue(), {                cell.dealImage.image = image            })        }        else {        }    })    }    else{        cell.dealImage.image = image    }  return cell}

Follow THIS tutorial for more Info. Hope this will help you.

New Solution:

Here is extension for it which is created by my friend Leo Dabus which is really simple to use:

extension UIImageView {    func downloadImageFrom(link link:String, contentMode: UIViewContentMode) {        NSURLSession.sharedSession().dataTaskWithURL( NSURL(string:link)!, completionHandler: {            (data, response, error) -> Void in            dispatch_async(dispatch_get_main_queue()) {                self.contentMode =  contentMode                if let data = data { self.image = UIImage(data: data) }            }        }).resume()    }}

Now in your cellForRowAtIndexPath method assign image to cell this way:

cell.cellImageView.image = UIImage(named: "placeholder")  //set placeholder image first.cell.cellImageView.downloadImageFrom(link: imageLinkArray[indexPath.row], contentMode: UIViewContentMode.ScaleAspectFit)  //set your image from link array.

And as Rob suggested into comment here is some useful libraries which you can use:

  1. https://github.com/Alamofire/AlamofireImage
  2. https://github.com/onevcat/Kingfisher
  3. https://github.com/rs/SDWebImage
  4. https://github.com/kean/DFImageManager


Since I can't comment just yet, here's a Swift 3 (Xcode 8 Beta 6) version of the useful extension provided by Leo Dabus.

extension UIImageView {    func downloadImageFrom(link:String, contentMode: UIViewContentMode) {        URLSession.shared.dataTask( with: NSURL(string:link)! as URL, completionHandler: {            (data, response, error) -> Void in            DispatchQueue.main.async {                self.contentMode =  contentMode                if let data = data { self.image = UIImage(data: data) }            }        }).resume()    }}

I'm using this inside a class that populates the table cell, it works like this in that context just fine, just in case any newbs were wondering if it will:

albumArt.image = UIImage(named: "placeholder")albumArt.downloadImageFrom(link: "http://someurl.com/image.jpg", contentMode: UIViewContentMode.scaleAspectFit)


Details

  • Xcode 10.2.1 (10E1001), Swift 5

Full sample

Info.plist (add value)

<key>NSAppTransportSecurity</key><dict>    <key>NSAllowsArbitraryLoads</key>    <true/></dict>

Podfile

target 'stackoverflow-28694645' do  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks  use_frameworks!  # Pods for stackoverflow-28694645  pod 'Alamofire'  pod 'AlamofireImage'end

Code

import UIKitimport Alamofireimport AlamofireImageclass ViewController: UIViewController {    private weak var tableView: UITableView?    private var items = [ItunceItem]()    override func viewDidLoad() {        super.viewDidLoad()        let tableView = UITableView()        view.addSubview(tableView)        tableView.translatesAutoresizingMaskIntoConstraints = false        tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true        tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true        tableView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor).isActive = true        tableView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor).isActive = true        tableView.tableFooterView = UIView()        tableView.register(TableViewCell.self, forCellReuseIdentifier: "TableViewCell")        tableView.rowHeight = 100        tableView.separatorColor = .clear        self.tableView = tableView        loadData()    }    private func loadData() {        let urlString = "https://itunes.apple.com/search?term=navigator"        Alamofire.request(urlString).response { [weak self] response in            guard let self = self, let data = response.data else { return }            do {                let decoder = JSONDecoder()                decoder.keyDecodingStrategy = .convertFromSnakeCase                self.items = try decoder.decode(ItunceItems.self, from: data).results                DispatchQueue.main.async { [weak self] in                    guard let tableView = self?.tableView else { return }                    tableView.delegate = self                    tableView.dataSource = self                    tableView.reloadData()                }            } catch let error { print("\(error.localizedDescription)") }        }    }}extension ViewController: UITableViewDataSource {    func numberOfSections(in tableView: UITableView) -> Int { return 1 }    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return items.count }    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell        return cell    }}extension ViewController: UITableViewDelegate {    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {        guard   let cell = cell as? TableViewCell,                let imageUrlString = items[indexPath.row].artworkUrl100,                let url = URL(string: imageUrlString) else { return }        cell.photoImageView?.af_setImage(withURL: url)    }    func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {        guard let cell = cell as? TableViewCell else { return }        cell.photoImageView?.af_cancelImageRequest()    }}struct ItunceItems: Codable { let results: [ItunceItem] }struct ItunceItem: Codable { var artworkUrl100: String? }class TableViewCell: UITableViewCell {    private(set) weak var photoImageView: UIImageView?    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {        super.init(style: style, reuseIdentifier: reuseIdentifier)        selectionStyle = .none        let imageView = UIImageView()        addSubview(imageView)        imageView.translatesAutoresizingMaskIntoConstraints = false        imageView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 6).isActive = true        imageView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor).isActive = true        imageView.leftAnchor.constraint(equalTo: safeAreaLayoutGuide.leftAnchor).isActive = true        imageView.rightAnchor.constraint(equalTo: safeAreaLayoutGuide.rightAnchor).isActive = true        imageView.contentMode = .scaleAspectFit        photoImageView = imageView    }    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }    override func prepareForReuse() {        super.prepareForReuse()        photoImageView?.image = nil    }}

Result

enter image description here