TableView inside specific UICollectionViewCell programmatically?
For those who need it, i found the solution:
class CustomizedCell: UICollectionViewCell, UITableViewDataSource, UITableViewDelegate { var tableView = UITableView() let cellIdentifier: String = "tableCell" override func layoutSubviews() { super.layoutSubviews() tableView.delegate = self tableView.dataSource = self tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellIdentifier) } func numberOfSections(in tableView: UITableView) -> Int { return 1 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 4 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: cellIdentifier) cell.textLabel?.text = "1 CUP" cell.detailTextLabel?.text = "Whole" return cell }}
Then at viewDidLoad method at CollectionView i did this:
collectionView?.register(CustomizedCell.self, forCellWithReuseIdentifier: "cell")
And after that i have called like this at cellForRowAt indexPath method of UICollectionView:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CustomizedCell return cell}
You can create a custom UICollectionView cell for that indexpath. And add a tableview in the cell xib.
Implement the delegate methods of tableview in custom cell class.
class CustomCollectionViewCell: UICollectionViewCell, UITableViewDataSource, UITableViewDelegate { @IBOutlet var tableView: UITableView! override func layoutSubviews() { super.layoutSubviews() tableView.delegate = self tableView.dataSource = self } }
The approaches above don't work well in with the MVC pattern. I recommend creating an NSObject subclass which conforms to UITableViewDelegate and UITableViewDataSource.
For example:
class DataProvider: NSObject, UITableViewDelegate, UITableViewDataSource { let dataManager = DataManager() let reuseId = "Cell" //MARK: - DataSource Methods func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return dataManager.data.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: reuseId, for: indexPath) cell.backgroundColor = .yellow return cell } //MARK: - Delegate Methods }
Now in your UICollectionViewCell subclass you can specify the tableView data source and delegate properties, like so:
class ContainerCollectionViewCell: UICollectionViewCell { @IBOutlet weak var label: UILabel! @IBOutlet weak var collectionView: UICollectionView! let dataProvider = DataProvider() let tableView: UITableView = { let table = UITableView() table.translatesAutoresizingMaskIntoConstraints = false return table }() override func awakeFromNib() { super.awakeFromNib() addSubview(tableView) tableView.fillSuperview() tableView.register(UITableViewCell.self, forCellReuseIdentifier: dataProvider.reuseId) tableView.delegate = dataProvider tableView.dataSource = dataProvider }}
Perhaps not perfect, but achieves better encapsulation than the above answers.