ios - 从 CellForRowAt 调用的函数更新 TableViewCell 中的 ImageView
问题描述
我尝试更新一个 ImageView 女巫是我的 TableViewCell 的一部分。每个单元格都有其他国家,对于每个单元格,我想下载该县的国旗并将其显示在单元格的 ImageView 中,所以我使用 CellForRowAt,准备好单元格的国家并调用一个下载国旗图像的函数. 但我不明白,如何更新 Cell 中的 ImageView ......
这是我的代码:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
// Configure the cell...
let stock = stocks[indexPath.row]
// Image downloading
loadCountryImage(country: stock.country)
return cell
}
func loadCountryImage(country: String) {
let url = "https://www.countryflags.io/\(country)/shiny/24.png"
guard let imageURL = URL(string: url) else {
print("no URL found")
return
}
let session = URLSession.shared
session.dataTask(with: imageURL) { imageData, _, _ in
let image = UIImage(data: imageData!)
}.resume()
那么现在图片下载成功了,但是如何在cell的imageView中获取呢?
来自德国的亲切问候!亚尼克
解决方案
简短的回答是将单元格传递给,loadCountryImage
以便您可以从数据任务更新闭包中的单元格图像。此更新需要分派到主队列。
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
// Configure the cell...
let stock = stocks[indexPath.row]
cell.imageView.image = somePlaceholderImage
// Image downloading
loadCountryImage(country: stock.country, in: cell)
return cell
}
func loadCountryImage(country: String, in cell:CustomCell) {
let url = "https://www.countryflags.io/\(country)/shiny/24.png"
guard let imageURL = URL(string: url) else {
print("no URL found")
return
}
let session = URLSession.shared
session.dataTask(with: imageURL) { imageData, _, _ in
guard let data = imageData, let image = UIImage(data: data) else {
return
}
DispatchQueue.main.async {
cell.imageView.image = image
}
}.resume()
}
长答案是您应该考虑缓存,并且由于单元格被重用,当表格视图滚动时会发生什么?您可能会获取过期的图像。一种方法是将国家/地区存储在单元格中并检查闭包以查看它是否仍然是您在设置图像之前所期望的。
您可以使用UITableviewDatasourcePrefetching
和NSCache
var imageCache = NSCache<NSString,UIImage>()
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
// Configure the cell...
let stock = stocks[indexPath.row]
cell.imageView.image = somePlaceholderImage
cell.country = stock.country
// Image downloading
loadCountryImage(country: stock.country, in: cell)
return cell
}
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
for indexPath in indexPaths {
let stock = stocks[indexPath.row]
if self.cache.object(forKey: stock.country) == nil {
self.loadCountryImage(country: stock.country, in: nil)
}
}
}
func loadCountryImage(country: String, in cell:CustomCell?) {
if let image = self.imageCache.object(forKey: country) {
cell?.imageView.image = image
return
}
let url = "https://www.countryflags.io/\(country)/shiny/24.png"
guard let imageURL = URL(string: url) else {
print("no URL found")
return
}
let session = URLSession.shared
session.dataTask(with: imageURL) { imageData, _, _ in
guard let data = imageData, let image = UIImage(data: data) else {
return
}
DispatchQueue.main.async {
self.imageCache.setObject(image, forKey: country)
if cell?.country == country {
cell?.imageView.image = image
}
}
}.resume()
}
一个更好的答案可能是查看像 SDWebImage 或 Kingfisher 这样的框架,它们为您做了很多这样的事情。
推荐阅读
- amazon-web-services - 如何在aws Elasticsearch中访问kibana url?
- c# - 为什么当我尝试添加新行时会出现此错误?
- javascript - 我在一个页面上多次重复使用同一个功能的次数
- python - Python SQL 按变量排序
- python - 我试着在 python 中制作同心正方形一段时间
- android - 在房间中复制 sqlite 数据库后刷新回收站视图
- python - 删除熊猫时间序列中的重复项
- powershell - PowerShell 调用 advapi32.dll GetEffectiveRightsFromAclA 崩溃 PowerShell
- r - 为什么 SPARQL 查询在 R 包中比在 Land Registry 中的查询时间长 30 倍?
- count - 将 setInterval 计数重置为零