IOS重用機制導致的UITableVIewCell或者UICollectionViewCell顯示錯誤

當我們使用UITableVIew和UICollectionView時都會遇到重用顯示問題。IOS系統默認會把標識相同的cell進行重用,你可以在創建cell的代理方法中是用UITableView的- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier方法或者UICollectionView的- (__kindof UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath方法來獲取重用棧的cell。

但是,如果你設置的內容和重用的內容沒有完全一致就會出現顯示錯誤。下面的例子用於說明:

class SubCategoryCollectionCell: BaseCollectionCell {

    @IBOutlet private weak var imageView: UIImageView!
    @IBOutlet private weak var label: UILabel!
    private var setImage: UIImage?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        label.font = UIFont.font6
        imageView.image = placeholderImage
    }
    
    @objc var image: Any! {
        didSet {
            setImage = nil // 返回初始狀態,以便url下載的圖片進行設置
            if let img = image as? UIImage {
                imageView.image = img
                setImage = img // 防止之後的url下載的圖片覆蓋
            } else if let urlString = image as? String {
                if urlString != "" {
                    if let url = URL.init(string: urlString) {
                        imageView.sd_setImage(with: url, placeholderImage: placeholderImage, options: .retryFailed, completed: { [weak self] (image, _, _, _) in
                            guard self != nil else {
                                return
                            }
                            if self!.setImage != nil {
                                self?.imageView.image = self!.setImage
                            } else {
                                self?.imageView.image = image ?? placeholderImage
                                self?.setImage = nil
                            }
                        })
                    }
                } else {
                    imageView.image = placeholderImage
                }
            }
        }
    }
    
    @objc var title: String! {
        didSet {
            label.text = NSLocalizedString(title, comment: "")
        }
    }

}

這個例子中的image是圖片數據,它可以是圖片、圖片的URL字符串。這個例子會出現2種情況:

1. 先設置URL字符串進行異步下載圖片的cell被系統重用後,使用靜態圖片設置。此時,異步下載的圖片還沒有完成(已經被系統重用了),當異步下載完成後,程序會重新設置圖片,導致圖片顯示不一致。在這種情況下,需要把設置的靜態圖片保存起來(因爲SDWebImage會默認設置圖片,所以不能用ImageView的image屬性判斷),在異步下載完成後,判斷存儲的靜態圖片是否存在,存在則重新設置靜態圖片。

2.先設置靜態圖片的cell被系統重用後,使用URL字符串進行異步下載圖片。這種情況下一般是不用處理的,但是由於第一種情況使用保存的靜態圖片作爲判斷條件,如果重新使用URL字符串進行異步下載圖片而且沒有把之前存儲的靜態圖片清除,在異步下載完成後,程序會把ImageView的Image屬性設置爲靜態圖片,導致圖片顯示錯誤。所以在每次設置圖片資源前和異步下載圖片完成後,把存儲的靜態圖片清除,以便異步下載圖片能夠正確設置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章