ios - UITableView (Swift 4) 中的奇怪缓存问题
问题描述
我的应用程序有一个非常奇怪的问题,我能想到的只是它是某种缓存问题。基本上,当我滚动时UITableView
,显示的缩略图会为同一行重新加载多次,通常每次使用不同的图像,然后最终到达正确的图像。
这里有一个简短(20 秒)的屏幕截图:https ://youtu.be/oa04mlOgMeQ
一旦加载,应用程序应该缓存这些图像,并且图像被命名为匹配奖励代码(并且名称在 JSON 文件中)。我无法弄清楚它为什么这样做。
编辑:这是我的 cellForRowAt 代码:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "BonusListViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? BonusListViewCell else {
fatalError("The dequeued cell is not an instance of BonusListViewCell.")
}
// let bonus = bonuses[indexPath.row]
let bonus: JsonFile.JsonBonuses
if isFiltering() {
bonus = filteredBonuses[indexPath.row]
} else {
bonus = bonuses[indexPath.row]
}
let urlString = "http://tourofhonor.com/appimages/"+(bonus.imageName)
let url = URL(string: urlString)
cell.primaryImage.downloadedFrom(url: url!)
cell.nameLabel.text = bonus.name.capitalized
cell.bonusCodeLabel.text = bonus.bonusCode.localizedUppercase
cell.categoryLabel.text = bonus.category
cell.valueLabel.text = "\(bonus.value)"
cell.cityLabel.text = "\(bonus.city.capitalized),"
cell.stateLabel.text = bonus.state.localizedUppercase
return cell
}
这是我的downloadedFrom
功能:
extension UIImageView {
func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = image
}
}.resume()
}
func downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloadedFrom(url: url, contentMode: mode)
}
}
我的 UITableViewCell 代码是:
import UIKit
class BonusListViewCell: UITableViewCell {
//MARK: Properties
@IBOutlet weak var bonusCodeLabel: UILabel!
@IBOutlet weak var categoryLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var valueLabel: UILabel!
@IBOutlet weak var cityLabel: UILabel!
@IBOutlet weak var stateLabel: UILabel!
@IBOutlet weak var flavorText: UITextView!
@IBOutlet weak var primaryImage: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
解决方案
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "BonusListViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? BonusListViewCell else {
fatalError("The dequeued cell is not an instance of BonusListViewCell.")
}
// let bonus = bonuses[indexPath.row]
let bonus: JsonFile.JsonBonuses
if isFiltering() {
bonus = filteredBonuses[indexPath.row]
} else {
bonus = bonuses[indexPath.row]
}
let urlString = "http://tourofhonor.com/appimages/"+(bonus.imageName)
let url = URL(string: urlString)
//set image url
cell.imageUrl = URL(string: images[indexPath.row])
cell.nameLabel.text = bonus.name.capitalized
cell.bonusCodeLabel.text = bonus.bonusCode.localizedUppercase
cell.categoryLabel.text = bonus.category
cell.valueLabel.text = "\(bonus.value)"
cell.cityLabel.text = "\(bonus.city.capitalized),"
cell.stateLabel.text = bonus.state.localizedUppercase
return cell
}
在你的牢房里
import UIKit
class BonusListViewCell: UITableViewCell {
//MARK: Properties
@IBOutlet weak var bonusCodeLabel: UILabel!
@IBOutlet weak var categoryLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var valueLabel: UILabel!
@IBOutlet weak var cityLabel: UILabel!
@IBOutlet weak var stateLabel: UILabel!
@IBOutlet weak var flavorText: UITextView!
@IBOutlet weak var primaryImage: UIImageView!
@IBOutlet weak var activity: UIActivityIndicatorView!
var imageUrl: URL? {
didSet {
loadImage()
}
}
var task: URLSessionDataTask?
override func awakeFromNib() {
super.awakeFromNib()
clean()
}
func loadImage() {
//you need cancel previous task
task?.cancel()
clean()
guard let imageUrl = imageUrl else {
return
}
activity.startAnimating()
task = URLSession.shared.dataTask(with: imageUrl) { [weak self] data, response, error in
DispatchQueue.main.async {
self?.activity.stopAnimating()
if error == nil, let data = data {
self?.primaryImage.image = UIImage(data: data)
}
}
}
task?.resume()
}
func clean() {
primaryImage.image = nil
}
}
但最好使用Alamofire或SDWebImage之类的库
推荐阅读
- python - 无法将检索到的表单数据应用于多个对象
- php - 使用 PHP 对联系表单 POST 进行服务器端验证,当它应该为真时,秘密返回假
- node.js - 在输入中记录数字时,我得到“未定义”
- r - 根据 R 中的规则加入 data.frames
- image - 使用 SSR 和 firebase 加载图像
- excel - 如何在excel中将字符串拆分为单个值
- python - 轮流使用 Discord.py 游戏
- java - JPA/Hibernate - LocalDate 正在转换为系统时区
- r - 与向量 2 中的元素重复向量 1 中的元素
- python - Plotly:蜡烛收盘点附近的细小水平线是什么?