Ahmadreza
Ahmadreza

Reputation: 7222

UICollectionView cellForItemAt not get called when I use a UICollectionView inside a UITableView cell on iOS 14

I know it sounds repetitive and millions of questions asked like this but when I use a collectionView inside a tableView cell on iOS 14, the collectionView cellForItemAt function is not called, it works on iOS 12.

I attached a demo project for it.

here is my tableView cell which has a collectionView inside i:

 class ServicesTableViewCell: UITableViewCell {
    
    @IBOutlet weak var parentView: UIView!
    @IBOutlet weak var collectionView: UICollectionView!
    
    var items = [String]()
    var data: ServiceRow?
    
    override func awakeFromNib() {
        super.awakeFromNib()
        
        collectionView.frame.size = CGSize(width: screenWidth, height: 50)
        collectionView.register(UINib(nibName: "ServiceFilterCell", bundle: Bundle.main), forCellWithReuseIdentifier: "ServiceFilterCell")
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.reloadData()
    }
    
    func fill(with data:ServiceRow) {
        items = data.items?.compactMap({$0.name}) ?? []
        parentView.backgroundColor = .clear
        collectionView.reloadData()
    }
}

extension ServicesTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { // <= This guy is not called
        let data = items[collectionView.tag]
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ServiceFilterCell", for: indexPath) as! ServiceFilterCell
        cell.fill(title: data, isSelected: false)
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 80, height: 40)
    }
}

here is my parent class tableView cellForRowAt:

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "ServicesTableViewCell", for: indexPath) as! ServicesTableViewCell
        cell.collectionView.tag = indexPath.section
        cell.fill(with: services[indexPath.section])
        cell.frame.size = CGSize(width: cell.frame.width, height: 50)
        cell.collectionView.reloadData()
        cell.layoutIfNeeded()
        return cell
    }

here is a screenshot for Tarun Tyagi answer:

enter image description here

Finally, the problem was that the xib file for tableViewCell was conformed to collectionViewCell when I created it, so I created a tableViewCell one & now everything works fine!

Upvotes: 1

Views: 1465

Answers (1)

Tarun Tyagi
Tarun Tyagi

Reputation: 10112

Check your layout code and make sure that at run time UICollectionView has a non-zero size (both width & height must be > 0).

In case any of width/height is zero, it doesn't need to display anything and hence it won't call your dataSource implementation for cellForItemAt:.

You can use View Hierarchy Debugger to check UICollectionView's width/height values at run time.

Upvotes: 3

Related Questions