I want to use lazy loading concept for my table view using swift. In my table view i am showing multiple cells which contain product images and product name . Please help me
Info.plist (add value)
NSAppTransportSecurity
NSAllowsArbitraryLoads
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 UIKit
import Alamofire
import AlamofireImage
class 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
}
}