當我們使用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屬性設置爲靜態圖片,導致圖片顯示錯誤。所以在每次設置圖片資源前和異步下載圖片完成後,把存儲的靜態圖片清除,以便異步下載圖片能夠正確設置。