如何不在 UICollectionView 中重用单元格 - Swift

Posted

技术标签:

【中文标题】如何不在 UICollectionView 中重用单元格 - Swift【英文标题】:How to NOT reuse cells in UICollectionView - Swift 【发布时间】:2018-12-14 16:41:27 【问题描述】:

我在 UITableView 的单元格中有 UICollectionView。此 UICollectionView 显示用户的个人资料照片。那里只有几件物品(假设最多 10 张照片)。

所以,我不想每次重复使用单元格时都从后端重新加载图像。这是不方便且不友好的用户体验。因此,我想创建 10 个单元格,将图像加载到其中并显示。

但我不知道如何在 UICollectionView 的“cellForItem”方法中创建(而不是出列)新的自定义单元格。或者如何禁止重用。

我是一个编程新手,所以如果你用简单的语言和最详细的解释我会很高兴。谢谢你。

这是我的代码:

设置CollectinView(上传随机本地照片用于测试):

extension PhotosTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return 10
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

        if indexPath.row == 0 
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "AddPhotoCollectionViewCell", for: indexPath)
            return cell
         else 
            var cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PhotoCollectionViewCell", for: indexPath) as! PhotoCollectionViewCell
            cell.photo = UIImage(named: "Photo\(Int.random(in: 1...8))") ?? UIImage(named: "defaultPhoto")
            cell.layer.cornerRadius = 10

            return cell
        
    

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 

        let height = collectionView.frame.height
        let width = (height / 16.0) * 10.0

        return CGSize(width: width, height: height)
    


我的自定义 PhotoCollectionViewCell:

class PhotoCollectionViewCell: UICollectionViewCell 

    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var heightConstraint: NSLayoutConstraint!
    @IBOutlet weak var widthConstraint: NSLayoutConstraint!

    var photo: UIImage! 
        didSet 
            // simulate networking delay
            perform(#selector(setImageView), with: nil, afterDelay: Double.random(in: 0.2...1))

            // setImageView()
        
    

    override func awakeFromNib() 
        super.awakeFromNib()
        // Initialization code
    

    @objc private func setImageView() 
        let cellHeight = self.frame.height
        let cellWidth = self.frame.width
        let cellRatio = cellHeight / cellWidth

        let photoRatio = photo.size.height / photo.size.width

        var estimatedWidth = cellWidth
        var estimatedHeight = cellHeight

        if photoRatio > cellRatio 
            estimatedWidth = cellWidth
            estimatedHeight = cellWidth * photoRatio
         else 
            estimatedHeight = cellHeight
            estimatedWidth = cellHeight / photoRatio
        

        widthConstraint.constant = estimatedWidth
        heightConstraint.constant = estimatedHeight
        imageView.image = photo
    

    override func prepareForReuse() 
        imageView.image = nil
    


【问题讨论】:

不要绕过单元重用,下载后将图像缓存到本地。 为什么不呢?重复使用没有什么意义,因为我只有几个单元格(不是很多),而且无论如何我都必须保留本地下载的图像。那么为什么不将其存储到单元格中呢?还是我听不懂? CollectionView 旨在复用单元格,这是 collectionView 的基础和最重要的一点。我认为您对重用的确切含义感到困惑,它只是意味着如果单元格不在屏幕上,则当前的单元格将被“重用”来设置它们,而不是一直创建和删除它们。 SDWebImage 和 Kingfisher 等框架可以为您处理图像缓存和重用。您将图像缓存与单元重用混淆了,虽然您可以通过关闭第二个来实现第一个,但您应该学习正确的做事方式 【参考方案1】:

只需在 cellForItemAt 中创建、填充和返回新的单元格对象,而不是将其出列,但这不是一种好的做法,您不应该这样做。

【讨论】:

感谢您的回答。是的,我更进一步,我无论如何都需要有照片数组(例如对于 ScrollView)。【参考方案2】:

您需要每次创建新单元格并为其分配值。尽管这样做非常危险,并且可能会导致您的应用过度使用大量内存,但您的应用会消耗更多电量并使设备变慢。

相反,我建议您将数据保存到集合中并随时重复使用。

【讨论】:

谢谢。我理解它并且已经这样做了:) 感谢您的回答和建议!

以上是关于如何不在 UICollectionView 中重用单元格 - Swift的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView 不重用单元格

UICollectionView 子类可在多个 viewController 中重用

注册大量 UICollectionViewCell 类以在 UICollectionView 中重用

UICollectionView 上的可重用性问题

照片框架和可重用的 UICollectionViewCell

在 UICollectionView 上禁用单元格重用