簡體   English   中英

UITableview、SDWebImage、單元重用和UIImage問題

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM