UICollectionView inside of UITableViewCell

11,664

Solution 1

This is working for me, I think the problems comes from the way you register your cell

class YourCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource {

@IBOutlet weak var collectionView: UICollectionView!

override func awakeFromNib() {
    super.awakeFromNib()
    registerCell()
    self.collectionView.delegate = self
    self.collectionView.dataSource = self
}
func registerCell() {
    collectionView.register(TimeCell.self, forCellWithReuseIdentifier: "cell")
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 10
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! TimeCell
    cell.time.text = "1:00"
    return cell
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

Solution 2

What I do, I use storyboard and setting the delegates & datasource from Storyboard by dragging into the classes.

a) Set TableView's delegates & datasource to ViewController enter image description here

b) Set CollectionView's delegates & datasource to TableViewCell(TheaterCell) enter image description here

ViewController Code:

class ViewController: UIViewController {

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}
}

extension ViewController:UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  return  1
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let theaterCell:TheaterCell = tableView.dequeueReusableCell(withIdentifier: "TheaterCell", for: indexPath) as! TheaterCell
    theaterCell.reloadCollectionView()
    return theaterCell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 200
}
}

TheaterCell Code:

class TheaterCell: UITableViewCell {
@IBOutlet var showtimesCollection: UICollectionView!
override func awakeFromNib() {
    super.awakeFromNib()
}

func reloadCollectionView() -> Void {
    self.showtimesCollection.reloadData()
}
}

extension TheaterCell: UICollectionViewDataSource, UICollectionViewDelegate {

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

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = showtimesCollection.dequeueReusableCell(withReuseIdentifier: "timeCell", for: indexPath) as! TimeCell
    cell.time.text = "1:00"
    return cell
}
}

TimeCell Code:

class TimeCell: UICollectionViewCell {
    @IBOutlet var time: UILabel!
}

Here is the output:

enter image description here

NOTE: IF YOU ARE NOT USING STORYBOARDS AND YOU MAKE COLLECTIONVIEW OR TABLE FROM CODE ONLY, THEN YOU HAVE REGISTER YOURS CELL AS: A) TheaterCell must be registered into ViewController class B) TimeCell must be registered into TheaterCell class

Share:
11,664
JSharpp
Author by

JSharpp

Updated on June 22, 2022

Comments

  • JSharpp
    JSharpp almost 2 years

    I am attempting to set a CollectionView inside of a TableViewCell. I have read through a hand full of stack questions, tuts, and videos and so far I have what appears to be the correct method but my collection view is still not loading into my table view cell.

    Code:

    import UIKit
    
    class TheaterCell: UITableViewCell {
    
    @IBOutlet var theaterName: UILabel!
    
    @IBOutlet var theaterLocation: UILabel!
    
    @IBOutlet var showtimesCollection: UICollectionView!
    
    override func awakeFromNib() {
        super.awakeFromNib()
    
        showtimesCollection.delegate = self
        showtimesCollection.dataSource = self
        showtimesCollection.reloadData()
    
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    
        // Configure the view for the selected state
    }
    
    }
    
    extension TheaterCell: UICollectionViewDataSource, UICollectionViewDelegate {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    
        return 10
    
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
        let cell = showtimesCollection.dequeueReusableCell(withReuseIdentifier: "timeCell", for: indexPath) as! TimeCell
    
        cell.time.text = "1:00"
    
        return cell
    
    }
    
    }
    

    The Tableview loads from the ViewController and is displaying its cells and elements but the collection view is not loading within the cell.

    • Mathias
      Mathias over 5 years
      Are your tableview cells appearing ?
    • JSharpp
      JSharpp over 5 years
      Yes, as stated in the question the tableview loads and displays the cells. The collection view does not load within the cells.
    • Rico Crescenzio
      Rico Crescenzio over 5 years
      Show the table view’s data source method
  • JSharpp
    JSharpp over 5 years
    I get a console error: Could not cast value of type 'UICollectionViewCell' (0x10e36bea0) to 'Film_Bee.TimeCell' (0x10533f688).
  • JSharpp
    JSharpp over 5 years
    I just checked through my table view again and I had not programmatically set the size for the row. Doing this along with your code without the registerCell func works.