启用分页时,UICollectionView会使隐藏的单元格出列

时间:2018-02-22 11:40:05

标签: ios swift uicollectionview programmatically

启用分页时,UICollectionView只会使3个单元格出列,其余单元格无缘无故地出列为隐藏状态。也许,这是UICollectionView一般工作的方式,但在我的项目中,我真的需要每当一个单元格出列时cellForItemAt indexPath: IndexPath method被调用它实际上创建了一个非隐藏的自定义{{1}实例。 1}}。

也许,它只创建3个实例,因为它需要正确管理内存。但是,在我的项目中,自定义UICollectionViewCell还包含另一个UICollectionViewCell,其中包含3个自定义collectionView单元格。这些collectionView个单元格中也有collectionView个数据,其中的数据封装在这些单元格中。我的主要问题是:为什么tableViews只在我的案例中创建3个实例,我该怎么做才能避免这种行为?

我实际项目中的层次结构如下所示:UICollectionView - > UICollectionView - > 3自定义UICollectionView - >每个UICollectionViewCell都包含UICollectionViewCell - >每个tableView都包含特定的自定义tableView

以下是我编写的整个代码,作为实际项目中的内容示例(这不是实际项目,但行为是相同的):

TableViewCell

ViewController

分机1

class ViewController: UIViewController {

    let cellId = "uniqueCellId"
    let sampleWords: [String] = ["one", "two", "three", "four", "five", "six"]
    let colors: [UIColor] = [.green, .yellow, .blue, .purple, .gray, .red]

    override func viewDidLoad() {
        super.viewDidLoad()
        registerCollectionViewCustomCell()
        prepareUI()
        setupViews()
        setCollectionViewLayoutToHorizontal()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    //collectionView is instantiated as a computed property. Initialized with a system flow layout. The frame is initially assigned to CGRect.zero because it is controlled by the constrains
    lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
        cv.backgroundColor = .white
        cv.layer.cornerRadius = 8
        cv.isPagingEnabled = true
        cv.delegate = self
        cv.dataSource = self
        return cv
    }()
}

分机2:

extension ViewController {
    private func prepareUI() {
        view.backgroundColor = UIColor.black
        navigationController?.navigationBar.barTintColor = .white
        navigationItem.title = "Collection View"
    }

    private func registerCollectionViewCustomCell() {
        collectionView.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
    }

    private func setCollectionViewLayoutToHorizontal() {
        if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.scrollDirection = .horizontal
        }
    }

    private func setupViews() {
        view.addSubview(collectionView)

        view.addConstraintsWithFormat(format: "H:|-15-[v0]-15-|", views: collectionView)
        view.addConstraintsWithFormat(format: "V:|-80-[v0]-140-|", views: collectionView)

    }
}

//configuring the dataSource and the delegate methods for the collectionView extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! CustomCollectionViewCell cell.backgroundColor = colors[indexPath.item] cell.wordLabel.text = sampleWords[indexPath.item] print("_____________________________________") print(cell.isHidden) if cell.isHidden { print("CUSTOM CELL INSTANCE NOT CREATED") } print("_____________________________________") return cell } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return sampleWords.count } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 0 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let size = CGSize(width: collectionView.frame.width, height: collectionView.frame.height) return size } } 上课:

CustomCollectionViewCell

Helper方法addConstraintsWithFormat:

//custom cell class
class CustomCollectionViewCell: UICollectionViewCell {

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
        print("instance of CustomCollectionViewCell is created")
    }

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

    let wordLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        return label
    }()

    private func setupViews() {
        addSubview(wordLabel)

        wordLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
        addConstraint(NSLayoutConstraint(item: wordLabel, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 70))
    }
}

这是我的所有代码。一切都是在没有//helper method to add constraints to a view extension UIView { func addConstraintsWithFormat(format: String, views: UIView...){ var viewsDictionary = [String : UIView]() for (index, view) in views.enumerated() { let key = "v\(index)" view.translatesAutoresizingMaskIntoConstraints = false viewsDictionary[key] = view } addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDictionary)) } } 的情况下完成的。

为了调试并了解自己发生了什么,我添加了一些打印语句: 1)“Print”语句,如果隐藏了一个单元格,则输出布尔值,如果是cell.isHidden - >是的 - >尚未创建自定义storyboard的实例。 2)init方法中自定义CollectionViewCell类中的“Print”语句,以查看是否已创建单元格。

输出始终如下:

CollectionViewCell

之后,cell.Hidden总是返回一个真值。

我发现有些人正在努力解决同样的问题。但解决方案对我没有帮助。因为我不在任何地方使用instance of CustomCollectionViewCell is created ______________________________________ false ______________________________________ instance of CustomCollectionViewCell is created ______________________________________ false ______________________________________ instance of CustomCollectionViewCell is created ______________________________________ false ______________________________________ ______________________________________ true CUSTOM CELL INSTANCE NOT CREATED 方法,我无法改变单个单元格的大小。 UICollectionViewCell gets hidden randomly

1 个答案:

答案 0 :(得分:0)

UICollectionView将在屏幕上立即显示为isHidden = false的单元格以及正在准备屏幕外的isHidden = true的其他单元格。这反映了显示视图时这些单元格将具有的实际状态。您无法通过设置isHidden来覆盖此行为,也不能覆盖hidden = false的状态。当单元格滚入和退出视图时,UICollectionView会自动更新此状态。

我实现了一个类似的结构,其中UICollectionViewCell包含另一个UICollectionView。 (一个水平滚动,第二个垂直滚动。)我可以断言,UICollectionView单元格没有必要isHidden = false来正确布局单元格的子视图。听起来你可能认为这个隐藏的属性是你遇到的问题的原因(我一直在那个确切的思路),但你实际上是错的,问题的原因是别的。

在我的情况下,为了记录,问题单元报告了一个自动布局约束冲突,我一直忽略它,因为我认为它是无关的。修复是在我将子视图添加到我的UICollectionViewCell后,我需要在我的单元格视图上调用layoutSubviews()并在其包含的集合视图上调用reloadData()。如果我没有这样做,嵌入式集合有时会工作,但是当它重新使用以前创建的单元格而不是创建新单元格时,由于自动布局冲突,它们将无法显示。这意味着有特定的路径可以实现或不会显示问题,具体取决于在以前的视图中创建的可重用的单元格。