UITableview、SDWebImage、单元格重用和UIImage问题



请参阅此处的视频示例:https://i.stack.imgur.com/A93hm.jpg

从互联网上异步下载带有图像的表视图。我能够让它们正确地填充,并且没有我自己的代码或SDWebImage的问题。当我将更多数据分页到表视图的末尾时,问题就开始了。寻呼确实有效。与所有文本数据一样,它在整个表视图中都能正常工作并保持正确。我的问题是我的ImageView。正如您在视频中看到的,分页后,UIImageViews图像会将上一次调用的所有单元格更改为表视图末尾最近单元格中的图像。是什么导致了这种行为,为什么它只发生在我的图像视图中,我该怎么做才能解决它?

我尝试在prepareForReuse中设置imageview image 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()

}

}

cellForRowAt

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的结果。后面几页的结果将不包括前面几页的方框图。

因此,您的方框图数据不再包括早期页面的方框图。您从最后一项中获取图像的原因是变量frontImageName和backImageName的作用域错误,它们应该是tableView(:cellForRowAt:(的本地变量

您需要通过调用dictionary.merge(_:uniquingKeysWith:(将API调用的结果与现有的boxart字典合并。请参阅https://developer.apple.com/documentation/swift/dictionary/3127171-merge详细信息

这是一个可重用性问题。请尝试更改单元格中的此行ForRowAtIndex。

tableview.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "cell(indexPath.row)")
let cell = tableView.dequeueReusableCell(withIdentifier: "cell(indexPath.row)", for: indexPath) as! ViewControllerTableViewCell

最新更新