【发布时间】:2020-09-12 15:25:29
【问题描述】:
在此处查看视频示例: https://imgur.com/a/vSBPjlP
有一个表格视图,其中包含从 Internet 异步下载的图像。我能够让它们正确填充,并且我自己的代码或 SDWebImage 都没有问题。当我将更多数据分页到表格视图的末尾时,我的问题就开始了。分页确实有效。与所有文本数据一样,它们都可以正常工作并在整个表格视图中保持正确。我遇到的问题是我的 ImageView。正如您在视频中看到的那样,在分页之后,UIImageViews 图像将所有单元格从上一次调用更改为看起来是表格视图末尾最新单元格中的内容的图像。是什么导致了这种行为,为什么它只发生在我的图像视图中,我可以做些什么来解决它?
我尝试将 prepareForReuse 中的 imageview 图像设置为零(违反 Apple 的建议),它产生了相同的结果。
相关代码
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
}
}
}
【问题讨论】:
-
后续页面的url没有设置include参数。看起来这导致盒子艺术被空内容覆盖。还要检查 frontImageName 和 backImageName 的范围。它们应该是 tableView(:cellForRowAt:) 的本地
-
@Dale 在 JSON 响应中返回后续页面的 URL,并包含原始调用中的所有参数。 JSON 中的 url 看起来像:'https://api.thegamesdb.net/v1/Games/ByPlatformID?apikey=MYAPIKEY&id=7&fields=players%2Cpublishers%2Cgenres%2Coverview%2Clast_updated%2Crating%2Cplatform%2Ccoop%2Cyoutube%2Cos%2Cprocessor %2Cram%2Chdd%2Cvideo%2Csound%2Calternates&include=boxart%2Cplatform&page=2 '
-
@Dale 很有趣,将前后 ImageName 的范围更改为本地使之前的图像现在默认为分页后的占位符图像。
-
后续页面返回的boxart是否返回之前页面的boxart?可能不是。您正在附加游戏的结果,但设置 boxart 的结果。
-
@Dale 我认为您在这里有所了解,并且一段时间以来它一直在我脑海中逐渐消失。我的问题是,在 JSON 响应中,boxarts 作为字典而不是像游戏数据这样的数组返回。如果返回的不是数组,我如何获取返回的盒子艺术数据并附加它?以下是返回的 JSON 示例:pastebin.com/5bV6UTcx
标签: ios swift uitableview sdwebimage