[英]UITableview, SDWebImage, cell reuse and UIImage problems
在此處查看視頻示例: https : //imgur.com/a/vSBPjlP
有一個帶有圖像的表格視圖,我從互聯網上異步下載。 我能夠讓它們正確填充,並且我自己的代碼或 SDWebImage 沒有問題。 當我將更多數據分頁到 tableview 的末尾時,我的問題就開始了。 分頁確實有效。 與所有文本數據一樣,它都可以正常工作並在整個 tableview 中保持正確。 我遇到的問題是我的 ImageView。 正如您在視頻中看到的那樣,分頁后, UIImageViews
圖像將所有單元格從上一次調用更改為 tableview 末尾最近單元格中的內容圖像。 是什么導致了這種行為,為什么它只發生在我的圖像視圖上,我該怎么做才能解決它?
我嘗試在prepareForReuse
設置 imageview 圖像 nil (反對 Apples 建議),它產生相同的結果。
相關代碼
API調用
func downloadGamesByPlatformIDJSON(platformID: Int?, fields: String?, include: String?, pageURL: String?, completed: @escaping () -> () ) {
var urlString : String?
if pageURL == nil {
urlString = "https://api.thegamesdb.net/v1/Games/ByPlatformID?apikey=\(apiKey)&id=\(platformID!)"
if fields != nil {
urlString = urlString! + "&fields=" + fields!
}
if include != nil {
urlString = urlString! + "&include=" + include!
}
} else {
urlString = pageURL!
}
let url = URL(string: "\(urlString!)")!
var requestHeader = URLRequest.init(url: url)
requestHeader.httpMethod = "GET"
requestHeader.setValue("application/json", forHTTPHeaderField: "Accept")
URLSession.shared.dataTask(with: requestHeader) { (data, response, error) in
if error != nil {
print("error = \(error)")
completed()
}
if error == nil {
do {
print("error = nil")
let json = String(data: data!, encoding: .utf8)
print(json)
if let jsonDecodedPlatforms = try JSONDecoder().decode(ByPlatformIDData?.self, from: data!) {
let decodedJSON = jsonDecodedPlatforms.data?.games
self.boxart = jsonDecodedPlatforms.include.boxart
self.baseURL = jsonDecodedPlatforms.include.boxart.baseURL
self.page = jsonDecodedPlatforms.pages
self.games.append(contentsOf: decodedJSON!
}
DispatchQueue.main.async {
completed()
}
} catch {
print(error)
}
}
}.resume()
}
分頁
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if offsetY > contentHeight - scrollView.frame.size.height {
if !fetchingMore {
beginBatchFetch()
}
}
}
func beginBatchFetch() {
fetchingMore = true
print("fetching data")
network.downloadGamesByPlatformIDJSON(platformID: nil, fields: nil, include: nil, pageURL: network.page?.next) {
print("pagination successful")
self.fetchingMore = false
self.tableView.reloadData()
}
}
單元格換行
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell
cell.configureCells()
//creating game object
let game1 : GDBGamesPlatform?
game1 = network.games[indexPath.row]
//retrieving the filename information based on the game id
if network.boxart?.data["\(game1!.id!)"]?[0].side == .front {
print(network.boxart?.data["\(game1!.id!)"]?[0].filename)
frontImageName = network.boxart?.data["\(game1!.id!)"]?[0].filename as! String
} else if network.boxart?.data["\(game1!.id!)"]?[0].side == .back {
backImageName = network.boxart?.data["\(game1!.id!)"]?[0].filename as! String
}
if network.boxart?.data["\(game1!.id!)"]?.count == 2 {
if network.boxart?.data["\(game1!.id!)"]?[1].side == .front {
frontImageName = network.boxart?.data["\(game1!.id!)"]?[1].filename as! String
} else if network.boxart?.data["\(game1!.id!)"]?[1].side == .back {
backImageName = network.boxart?.data["\(game1!.id!)"]?[1].filename as! String
}
}
//creating image url string
var imageUrlString = network.baseURL!.small + frontImageName
print(imageUrlString)
let imageURL = URL(string: imageUrlString)
//if data exists for the front cover image download it, otherwise show default image
if frontImageName != nil {
cell.loadCoverImageWith(urlString: imageUrlString)
} else {
cell.tableViewCoverImage.image = UIImage(named: "noArtNES")
}
return cell
}
import UIKit
import SDWebImage
class ViewControllerTableViewCell: UITableViewCell {
@IBOutlet weak var tableViewCoverImage: UIImageView!
@IBOutlet weak var tableViewGameName: UILabel!
@IBOutlet weak var tableViewGenreLabel: UILabel!
@IBOutlet weak var tableViewAgeRatingLabel: UILabel!
@IBOutlet weak var tableViewCompanyLabel: UILabel!
@IBOutlet weak var tableViewReleaseDateLabel: UILabel!
@IBOutlet weak var backgroundCell: UIView!
@IBOutlet weak var tableViewCoverRearImage: UIImageView!
@IBOutlet weak var gameCartImage: UIImageView!
override func prepareForReuse() {
super.prepareForReuse()
tableViewCoverImage.sd_cancelCurrentImageLoad()
tableViewCoverImage.image = nil
}
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
}
func loadCoverImageWith(urlString: String) {
let imageURL = URL(string: urlString)
self.tableViewCoverImage.sd_setImage(with: imageURL, placeholderImage: UIImage(named: "noArtNES"), options: SDWebImageOptions.highPriority) { (image, error, cacheType, url) in
if let error = error {
print("Error downloading the image. Error Description: \(error.localizedDescription)")
} else {
let edgeColor = self.tableViewCoverImage.image?.edgeColor()
self.tableViewCoverImage.layer.shadowColor = edgeColor!.cgColor
}
}
}
func configureCells() {
tableViewCoverImage.layer.shadowOffset = CGSize(width: -5, height: 8)
tableViewCoverImage.layer.shadowRadius = 8
tableViewCoverImage.layer.shadowOpacity = 0.8
tableViewCoverImage.layer.cornerRadius = 10
tableViewCoverImage.clipsToBounds = false
tableViewCoverImage.layer.masksToBounds = false
backgroundCell.layer.shadowOffset = CGSize(width: 0, height: 5)
backgroundCell.layer.shadowRadius = 5
backgroundCell.layer.shadowOpacity = 0.1
backgroundCell.layer.cornerRadius = 10
if self.traitCollection.userInterfaceStyle == .light {
backgroundCell.layer.shadowColor = UIColor.black.cgColor
backgroundCell.layer.backgroundColor = UIColor.white.cgColor
} else {
backgroundCell.layer.shadowColor = UIColor.white.cgColor
backgroundCell.layer.backgroundColor = UIColor.black.cgColor
}
}
}
對 API 的第二次和以后的調用會將游戲的結果附加到數組中,但會覆蓋 boxart 的結果。 后面幾頁的結果將不包括前面幾頁的插圖。
因此,您的 boxart 數據不再包含早期頁面的藝術。 您從最后一項獲取圖像的原因是變量 frontImageName 和 backImageName 的范圍錯誤,它們應該是 tableView(:cellForRowAt:) 的本地變量
您需要通過調用 Dictionary.merge(_:uniquingKeysWith:) 將 API 調用的結果與現有的 boxart 字典合並。 有關詳細信息,請參閱https://developer.apple.com/documentation/swift/dictionary/3127171-merge
這是一個可重用性問題。 嘗試更改 cellForRowAtIndex 中的這一行。
tableview.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "cell\(indexPath.row)")
let cell = tableView.dequeueReusableCell(withIdentifier: "cell\(indexPath.row)", for: indexPath) as! ViewControllerTableViewCell
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.