ios 如何使用swift在表格视图中实现图像的延迟加载
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28694645/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to implement lazy loading of images in table view using swift
提问by Vikram Pote
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 to get the solution.
我想使用 swift 为我的表视图使用延迟加载概念。在我的表格视图中,我显示了多个包含产品图片和产品名称的单元格。请帮助我获得解决方案。
回答by Dharmesh Kheni
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 THIStutorial for more Info. Hope this will help you.
按照本教程获取更多信息。希望这会帮助你。
New Solution:
新解决方案:
Here is extension for it which is created by my friend Leo Dabuswhich is really simple to use:
这是它的扩展,由我的朋友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()
}
}
Now in your cellForRowAtIndexPath
method assign image to cell this way:
现在在您的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.
And as Robsuggested into comment here is some useful libraries which you can use:
正如Rob在评论中所建议的,这里有一些有用的库,您可以使用它们:
回答by Brad Root
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.
由于我还不能发表评论,这里是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()
}
}
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)
回答by Vasily Bodnarchuk
Details
细节
- Xcode 10.2.1 (10E1001), Swift 5
- Xcode 10.2.1 (10E1001),Swift 5
Full sample
完整样品
Info.plist (add value)
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
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
}
}