collectionView.dequeueReusableCell不调用Cell的init

时间:2019-08-10 20:27:47

标签: swift uicollectionview uicollectionviewcell uicollectionviewlayout reloaddata

当用户触摸集合视图单元格时,它会展开到全屏。然后,您单击一个x按钮,它会缩小回到集合视图中。

问题是,我调用collectionView.reloadItems(),并且它仅在第一次调用单元格init函数。每次之后,它都会调用cellForItem(at: ),后者会调用collectionView.dequeueReusableCell(),但不会再次调用该单元格的init,这会使该单元格中的内容不显示。

使单元格全屏,然后按X键重新加载项目,并将其放回集合视图中的正常大小

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        guard let cell = collectionView.cellForItem(at: indexPath) as? CollectionViewCell else { return }

        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: [], animations: {
            self.navigationController?.setNavigationBarHidden(true, animated: true)

            // make cell full screen
            cell.frame = collectionView.bounds
            cell.superview?.bringSubviewToFront(cell)

            //disable scroll
            collectionView.isScrollEnabled = false

            // make overlay full screen
            cell.imageView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height)

            // show X button
            cell.showXBtn()

            cell.xBtn.onTapped = {
                // enable scroll
                collectionView.isScrollEnabled = true

                // shrink back to collection view
                collectionView.reloadItems(at: [indexPath])

                // hide x button
                cell.hideXBtn()

                // show navigation bar
                self.navigationController?.setNavigationBarHidden(false, animated: true)
            }
        }, completion: nil)     
    }

如果我在这里调用cell.setup(),则代码可以正常工作。如果我尝试在单元格的init函数(或didMoveToSuperview())中调用cell.setup(),则只能在第一次调用collectinView.reloadItems()时起作用。

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

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,
                                                      for: indexPath) as! CollectionViewCell
        // setup cell. If I call it within the cell, it only works the first time I call collectionView.reloadItem()
        cell.setup()

        // ignore spelling error lol
        let image = UIImage(named: "bdyaFilter")!
        cell.imageView.image = image

        return cell
    }

我的手机。只有在我第一次尝试重新加载项目时才调用init

class CollectionViewCell: UICollectionViewCell {
    let imageView = UIImageView()
    let xBtn = XButton()

    override init(frame: CGRect) {
        super.init(frame: frame)
        // this is only called the first time i call collectionView.reloadItems()
       // setup()
    }
    func setup() {
        self.backgroundColor = .orange
        self.layer.cornerRadius = 15
        self.layer.masksToBounds = true

        addImageView()
        addXBtn()
        hideXBtn()
    }
    private func addImageView() {
        imageView.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height)
        self.addSubview(imageView)
    }
    func addXBtn() {
        xBtn.frame = CGRect(x: 25, y: 25, width: 30, height: 30)
        self.addSubview(xBtn)
    }    
    func hideXBtn() {
        xBtn.isHidden = true
    }  
    func showXBtn() {
        xBtn.isHidden = false
    } 

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

1 个答案:

答案 0 :(得分:1)

这就是collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifierfor:)的重点。要回收单元对象,而不是在用户滚动时分配和释放一大堆对象。

您需要自己调用setup(),最好使用prepareForReuse()方法,并提供单元格可能需要的任何新值。

  

如果您为指定的标识符注册了一个类,并且必须创建一个新的单元格,则此方法通过调用其init(frame:)方法来初始化该单元格。对于基于笔尖的单元格,此方法从提供的笔尖文件中加载单元格对象。如果现有单元可供重用,则此方法将改为调用该单元的prepareForReuse()方法。

来自the documentation of UICollectionView.dequeueReusableCell(withReuseIdentifier:for:)