如何使用swift在表视图中实现延迟加载图像

时间:2015-02-24 11:30:03

标签: ios iphone swift uitableview

我想使用swift在我的表视图中使用延迟加载概念。在我的表视图中,我显示了多个包含产品图像和产品名称的单元格。 请帮我解决问题。

3 个答案:

答案 0 :(得分:36)

旧解决方案:

因为您没有显示任何代码。

以下是您的示例。

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

}

关注THIS教程了解更多信息。希望这会对你有所帮助。

新解决方案:

以下是我的朋友Leo Dabus创建的扩展程序,它非常简单易用:

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()
    }
}

现在,在cellForRowAtIndexPath方法中,以这种方式将图像分配给单元格:

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.

正如Rob建议在这里评论一些有用的库你可以使用:

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

答案 1 :(得分:12)

由于我还不能评论,这里是Leo Dabus提供的有用扩展的 Swift 3 (Xcode 8 Beta 6)版本。

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()
    }
}

我在填充表格单元格的类中使用它,它在这种情况下就像这样工作就好了,以防任何newbs想知道它是否会:

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

答案 2 :(得分:3)

详细

  • Xcode 10.2.1(10E1001),Swift 5

完整样本

  

Info.plist(增值)

<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
  

代码

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
    }
}

结果

enter image description here